|
Start by reading Nick's article, Creating a CCW for COM-enabled non-.NET Applications[^], and read Exposing .NET Framework Components to COM[^] in the .NET Framework SDK for more detailed information.
Can you create reliable COM components in C#? I don't know, can you? C# is a language, it doesn't create anything - you do. One of the goals of COM is to create a system where language is not so much an end as it is a means. You can write COM components in C++, VB6, and many other languages, as well as languages targeting the CLR (like C#) that make use of the interop services. It is fully supported and one of many viable means to writing COM components. How reliable it is depends on you.
The default shim, mscoree.dll, is also a factor, but I work with a heck of a lot of interop (both CCWs, RCWs, and P/Invoke) and have never had a problem with the shim itself.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I got two questions about creating a package using c# & Windows Installer in Visual Studio .NET:
Question 1
I want to enable the user to choose during setup whether he wants to add a shortcut to the desktop or not. I did the following but it does't seem to work:
1. I added a two button RadioButtons dialog box to the Start section (User Interface) to enable the user can select whether he wants or does not want to add a shortcut to the desktop
2. I gave the ButtonProperty the name SELECTSCHORTCUT. If the selection is Yes, the value wil be 1 and if the selection is No the value will be 2
3. In the file File System menu I added a condition for the User's Desktop. The condition is SELECTSHORTCUT = "1"
Can someone tell me what I do wrong?
QUESTION 2
Scenario
1. I go to the User Interace editor and add a two button RadioButtons interface to the Start section (i.e. to enable the user to select whether he want to add a desktop shortcut during installation)
2. Now I want to add one more two buttons RadioButton dialog box to ask whether the user wants to use SQL server or MS Access database. The odd thing is that once I have used a dialog box, I don't seem to be able to add another similar type dialog box the installer. Somehow Visual Studio restricts using two times a RadioButtons Dialog during installation. Why is this and how can I resolve this? I really need to be able to have multple 2 button RadioButtons dialogs during installation
How is able to give an answer on the two problems raised above? Any help is greatly appreciated.
Lieperik
|
|
|
|
|
First, don't use a RadioButton like this: checkboxes are a better alternative (implicitly yes/no controls) and are more common with yes/no questions such as you're using. Using this method, your property is either undefined or null if unchecked, or defined as the constant value you pick if checked. Your condition then merely has to use the property name, like SELECTSHORTCUT . You can still check for the check value, but it's really not required.
Don't add this condition to the Desktop folder, though - it always exists and is assigned when the MSI runtime is loading. Add the condition to your actual shortcut item in the project's File System Editor window.
Finally, regarding your last question: I've been authoring MSI packages since MSI 1.0 beta and am currently on the 3.0 beta team. I've used about every major Windows Installer authoring package and not one is near as bad as those for Visual Studio (especially the add-in for Visual Studio 6 ). the Installer project is not meant to be a commercial deployment solution, however. It's good for deploying internal libraries, samples, and smaller projects from smaller companies. If you want real control, either learn and understand the MSI database and use Orca from the Windows Installer SDK, or look at commercial solutions like Wise Solutions[^] or InstallShield[^]. I personally and professional use the former, since it is much cheaper (and just as capable) and have provided unhindered access to the MSI database before compiling, where InstallShield for Windows Installer didn't add full exposure till version 4.0 (and it's MUCH more expensive).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Many thanks for your prompt reply. Your feedback is a great help. One last question if you don't mind:
You noted:
"Don't add this condition to the Desktop folder, though - it always exists and is assigned when the MSI runtime is loading. Add the condition to your actual shortcut item in the project's File System Editor window."
The strange thing is that there is no condition property for the shortcuts (I am using Visual Studio .NET). The only properties shown for the shortcut are: Arguements, Description, Folder, Icon, ShowCmd, Target, Transitive and Working Folder.
Without seeing the propery condition for the shortcut, how can I attached the condition to the shortcut.
Cheers, Lieperik
http://c-sharp.pagina.nl
http://c-sharp.prikpagina.nl
|
|
|
|
|
Yeah, I suppose you're right. I rarely use the Windows Installer projects in VS.NET, sorry.
You can set the condition for the file itself. Files are grouped into Components (guidelines state one executable per component, as well). Components are grouped into Features. Shortcuts are associated with a Component. So, the condition on the file is actually a condition on the Component (files don't have conditions - their components do). Since the shortcut is "tied" to that component, then the component shouldn't installed at all.
The problem is that you only want the shortcut optional, not the component. In this case, you must associate the Shortcut table entry with a new Component that uses this condition, and then associate that Component in the Features table of the MSI package. You can leave the KeyPath field of the Component table record null.
This requires that you install Orca from the Windows Installer SDK, which is part of the Platform SDK[^].
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi Heath,
Thanks again. right now I am downloading the Windows Installer SDK and will install Orca and have a go on that.
Cheers, Lieperik
____________________
http://c-sharp.pagina.nl
http://c-sharp.prikpagina.nl
|
|
|
|
|
I declare a ComboBox in a class. The box never actually shows up on a form, but the variable for the box exists, and is initialized. What is confusing me is that I tried setting the datasource and valuemember of this combo box to a table in a dataset, but nothing is being put into the list of my combobox. I'm pretty confused, so some advice or suggestions would help. Thanks!
|
|
|
|
|
It doesn't matter if you declare a variable or not, you must add it to the parent control's Controls collection property, just like all the other controls. Expand the "Windows Form Designer generated code" region and look at the InitializeComponent method that the designer code serializer uses for examples, and see the Control.Controls property documentation in the .NET Framework SDK.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Excellent help as always. Thanks Heath, worked perfectly.
|
|
|
|
|
Has enyone done this with C#?
regards
GG
|
|
|
|
|
Absolutely! Here is what you need to do.
Add these declarations inside your class:
[StructLayout(LayoutKind.Sequential)]
private class NETRESOURCE
{
public Int32 dwScope;
public Int32 dwType;
public Int32 dwDisplayType;
public Int32 dwUsage;
public string lpLocalName;
public string lpRemoteName;
public string lpComment;
public string lpProvider;
}
[DllImport("mpr.dll")]
private static extern Int32 WNetAddConnection2 (
NETRESOURCE lpNetResource,
[MarshalAs(UnmanagedType.LPTStr)] string lpPassword,
[MarshalAs(UnmanagedType.LPTStr)] string lpUsername,
Int32 dwFlags);
[DllImport("mpr.dll")]
private static extern Int32 WNetCancelConnection2 (
[MarshalAs(UnmanagedType.LPTStr)] string lpResourceName,
[MarshalAs(UnmanagedType.Bool)] bool bForce);
THen Write a function:
void MapShareToDrive(string share, string, localdrive, string username, string password);
{
NETRESOURCE netResource = new NETRESOURCE();
netResource.dwScope = 1;
netResource.dwType = 1;
netResource.lpLocalName = localdrive;
netResource.lpRemoteName = share;
int iRetVal = WNetAddConnection2(netResource, password, username, 0);
if (iRetVal != 0)
{
throw new System.IO.IOException("Failed to gain access to network share. Error code: " + iRetVal);
}
}
EDIT: Changed marshaling for string parameters to [MarshalAs(UnmanagedType.LPTStr)] .. but anyway my code would work fine on Windows NT and later
|
|
|
|
|
Problem: WNetAddConnectoin2 uses LPCTSTR , or system-dependent string encodings (ANSI for Windows, Unicode for Windows NT). You either need to marshal these as UnmanagedType.LPTStr , or using [DllImport("mpr.dll", EntryPoint="WNetAddConnectoin2A", CharSet=CharSet.Ansi)] to always use the ANSI version of the API exported by mpr.dll on both platforms. The former method is recommend, however. Take advantage of Unicode whenever you can.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
private class NETRESOURCE
{
public Int32 dwScope = 0;
public Int32 dwType = 0;
public Int32 dwDisplayType = 0;
public Int32 dwUsage = 0;
public string lpLocalName = null;
public string lpRemoteName = null;
public string lpComment = null;
public string lpProvider = null;
}
[DllImport("mpr.dll")]
private static extern Int32 WNetAddConnection2
(NETRESOURCE lpNetResource,
[MarshalAs(UnmanagedType.LPTStr)] string lpPassword,
[MarshalAs(UnmanagedType.LPTStr)] string lpUsername,
Int32 dwFlags);
[DllImport("mpr.dll")]
private static extern Int32 WNetCancelConnection2
([MarshalAs(UnmanagedType.LPTStr)] string lpResourceName,
[MarshalAs(UnmanagedType.Bool)] bool bForce);
public void MapShareToDrive(string share, string localdrive, string username, string password)
{ // Prepare for network access
NETRESOURCE netResource = new NETRESOURCE();
netResource.dwScope = 1;
netResource.dwType = 1; //RESOURCETYPE_DISK
netResource.lpLocalName = localdrive;
netResource.lpRemoteName = share;
// Connect to network share
int iRetVal = WNetAddConnection2(netResource, password, username, 8);
// You can also do the following to make the system prompt for username/password
// int iRetVal = WNetAddConnection2(netResource, "", "", 16);
if (iRetVal != 0)
{
throw new System.IO.IOException("Failed to gain access to network share. Error code: " + iRetVal);
}
}
Hi if I used the code example with parameter dwFlags = 0 then I always got error = 5.
If I changed the parameter dwFlags = 8 then the dialog for mapping network prompted?
If I am understanding things right I thought the parameter dwFlags = 16 should prompt the mapping dialog.
Best regards,
Gardar
|
|
|
|
|
Another quick and dirty alternative to Roman's (although I'd prefer that way in production code) is to simply use the Process class to start the net.exe application with the necessary command-line arguments.
For example, barring any requirements for a username and password, you could do it as simply as this:
public void MapDrive(char drive, string path)
{
Process.Start("net.exe", string.Format("{0}: {1}", drive, path));
} That's very simplistic and you might want to look at the overloads for Process.Start to hide the console window that would be displayed automatically (in Windows, this is unavoidable; in Windows NT, you can stop the PE loader from displaying the console window for executables using the console subsystem).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks very much for this, I will try both ways.
Regards,
Gardar
|
|
|
|
|
I read a posting somewhere (I think on the CP but I cannot find it) about using Visual Studio 6 to write .Net code. I mentioned it to a friend and he wants to give it a try but I cannot find the article. Has anyone done this before??
|
|
|
|
|
You don't need Visual Studio (any version) at all. Download the .NET Framework (that alone is enough) and the SDK for more tools (like the IL Disassembler, ildasm.exe). Any vanilla text editor will do. When writing samples for the C# forum here, I typically write-up something (if I feel like testing it, or debugging someone else's code when the problem is elusive) using console-mode VIM[^]. I then use the command-line compilers (like csc.exe, resgen.exe, licgen.exe, etc.) and - viola - you have a program.
If it is possible using VS6, it's definitely a massive hack and probably doesn't include very good designer support. I wouldn't recommend it.
Optionally heading that warning, http://www.google.com[^] can find just about anything if you use the right keywords.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath Stewart wrote:
using console-mode VIM[^].
You heathen!
Sorry, I'm in an odd mood today...had beer for a work-lunch-meeting, so now I want a nap...
Jeremy Kimball
Moderation is for monks. -Lazarus Long
And this, too, shall pass away...
|
|
|
|
|
What, you expect me to use emacs?!
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hello.
After analyzing the software industry, I believe C# and .NET are and will remain apart of a major set of development tool on the Win32 and Win64 platform second to only a combination of C/C++. With that in mind, I would like to ask what is the most complete and advanced programming book on C#/.NET?
Here are the books I am considering.
Programming Microsoft .NET by Jeff Prosise
Pro: Very good overall
Con: Broad and emphasizes .ASP
Programming Windows with C# (Core Reference) by Charles Petzold
Pro: Complete - discusses all GUI tools, etc.
Con: Fundamental - many examples of Windows Forms and no advanced design including multithreading, etc.
Applied Microsoft .NET Framework Programming by Jeffrey Richter
Pro: Extensive coverage of CRT and .NET
Con: Overrated, lacking advanced subjects including multithreading, etc. It is not like his previous book on Win32 programming.
I am trying to buy as few books as possible and still acquire a good overall understanding of C#/.NET and extensive converage of the framework for maximizing an application's performance. I am interested in multithreading, multiple processes, memory mapping, IPC, serial communication, socket, etc.
I believe I can learn the specifics (GUI) via experimenting, MSDN, and of course forums.
Thanks,
Kuphryn
|
|
|
|
|
Read the .NET Framework SDK, including all the topics. The ending is obvious, but it's still thrilling.
And don't forget the Framework Class Library (FCL) anthology, which you can find in %WINDIR%\Microsoft.NET\Framework\v1.X.XXXX. It's best read with ildasm.exe from the .NET Framework SDK - and previously reading up on IL is helpful - but can be read with others tools like .NET Reflector[^].
Best darn books I've ever read.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath Stewart wrote:
Best darn books I've ever read.
Those are the book recommendations I would expect from you Heath, absolutely.
- Nick Parker My Blog | My Articles
|
|
|
|
|
I have a two classes A and B
public class A
{
private static ArrayList allobjects=new ArrayList();
private static int objcount=0;
public A()
{
objcount++;
allobjects.Add(this);
}
public static A[] AllObjects
{
get{return allobjects.ToArray(typeof(A)) as A[];}
}
}
public class B:A
{
public B()
{}
} When I construct a B object it is added to the allobjects array fine.
However at random times, when I look at A.AllObjects in the debugger, there are more objects than what I added. For example if I construct one and I look at it there will be 7 in the array. Furthermore, if I look at A.allobjects[0].allobjects, this array will contain 13, if I go further I'll get 19 and so forth. If I put a breakpoint in the constructor, it never hits the breakpoint, yet objcount will reflect the number of objects in the array depending on how deep I go. So any A.allobjects[0].objcount=7, and A.allobjects.[0].allobjects[0].objcount=13 and so forth. This is bugging me out especially since I have a breakpoint in the constructor and that is the only place that objcount is incremented.
Any help would be greatly appreciated.
K
|
|
|
|
|
Hi
I got a question, how can I access to a DataSet or any object from another Form in the same project??.
I have a main form, (no MDI), and show a dialog, but I wanna that dialog use a Dataset from the main form.
Thanks.
----
hxxbin
|
|
|
|
|
If you design your application properly things like datasets won't be controlled by forms so you shouldn't need to pass a dataset between forms.
Here is a good place to start: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/DesMVC.asp[^]
Also, analysing the way you asked your question ("from another Form in the same project") I have some doubts about your understanding of Object Orientation. So you may like to read also http://www.codeproject.com/useritems/beginneroop.asp[^] which was written with examples in C++ but the concept equally applies to C#
Finally, to actually answer your question I have provided a example implementation.
In the method in the main form that opens the dialog do something like this:
DialogForm dlg = new DialogForm();
dlg.TheDataset = this.myDataset;
dlg.ShowDialog();
where:
this.myDataset is your dataset
and
dlg.TheDataset is defined in your Dialog Form's class as
public Dataset TheDataSet
{
set
{
this.theDataset = value;
}
}
and that the Dialog Form also has a field defined as:
private Dataset theDataset
Does this help?
"You can have everything in life you want if you will just help enough other people get what they want." --Zig Ziglar
"On two occasions, I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able to rightly apprehend the kind of confusion of ideas that could provoke such a question."
--Charles Babbage (1791-1871)
|
|
|
|
|