Forgive me if my title is not accurate, I did my best to describe my issue.
Here's the details, I can modify accordingly:
I've been upgrading a VB6 application to a .NET (VB.NET and C#) application to be used in Excel. Using my application's ProgID, I can query it in Excel VBA using:
CreateObject("MyExe.MyApp")
Since I believe my app is a single-instance application, when I call CreateObject and it is already running, it just returns me that running instance. All is fine there.
My issue is, when it is NOT running, it will launch a new one right? That's my problem in my .NET application. You see, in VB6, when you use CreateObject, it will change my App.StartMode to VbSModeAutomation = 1
My VB6 application handles this accordingly. However, there doesn't seem to be an equivalent way of doing this for a .NET application. In fact, it says right on this MSDN page:
StartMode - No equivalent. In Visual Basic 6.0, this property was used
to start an application as an ActiveX component. ActiveX component
creation is not supported in Visual Studio .NET.
So ultimately, my question is: how do I determine when my .NET application is started from this call to CreateObject versus starting it manually (or via standealone, like a shortcut or etc.)?
.NET does not as easily let you create an out-of-process COM server, like VB6 does with that VbSModeAutomation property. The supported scenario is COM+ hosting, your [ComVisible] class needs to derive from the ServicedComponent class.
There's a dedicated KB article that summarizes the required steps pretty well. The in-depth MSDN articles start here.
Checking for a parent process is quite tricky but you can find the information in the Win32_Process WMI class - ParentProcessID property. If this is not set then your application was not started by another application.
You might be able to use the CommandLine to determine how it starts. It does not appear that CreateObject allows you to pass command args, but as you noted, -Embedding seems to automatically get sent. Alternatively, maybe you could modify the shortcut method to pass some fake argument and its absence could indicate a CreateObject start method.
NET supports several ways to get the commandline:
Environment.CommandLine and Environment.CommandLineArgs()
I think there is another in the VB Namespace but it returns a collection of objects rather than String or String array of parsed args (space delimited).
You can also modify your Sub Main:
Public Sub Main(args() As String)
NET will fill in the array with the parsed commandline
Related
I'm trying to configure access, launch permissions along with set run as to one of our custom DCOM application.
I have already gone through these links
dcomcnfg functionality programmatically
and http://www.myitforum.com/articles/11/view.asp?id=9323 (downloaded c++ DCOMPerm library)
I tried the code from the first link above as is written by "longofest" but the following line of code
var value = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", "DefaultAccessPermission", null);
always gives me back a null value,however when I looked into the registry entries on my machine the "DefaultAccessPermission" entry for Ole registry key does have a binary value there then why I always receive a null back, no idea.
Secondly I tried the c++ library downloaded from the second link above and tried to do a COM call to one of the methods with DLLImport attribution (for automating the launch permissions for the DCOM object) but some marshalling issue is not letting me pass in the C# types corresponding to C++ types and spitting out an exception that says PInvoke cannot return variants.
I couldn't find anything concrete after googling for several hours, any help on this account will be more than appreciated.
Never worked with C++, got very poor knowledge of this language.
Update:The null value issue is solved but I don't know how to set access permissions and set run as. I have seen in c++ code that for setting access permission the code needs a domain and username but what is the c# equivalent of that, no idea....
I used the tblimp.exe tool from Microsoft and created an interop .dll assembly out of DComPerm.dll (c++ assembly) to reference in C# code and by means of Run Time Callable Wrapper I'm calling various methods on COM objects to write my C# program, so no need of DLLImport or MarshalAs attribution since RCW will take care of all the marshalling and unmarshalling issues.
My company has created several COM objects and they were using them happily from .NET. But now, our client wants to change to Java. I thought it would be interesting to use JACOB or j-interop (I'm not sure which of them) for some tasks, but the resultant code is pretty unmanageable. So I want to write a tool that can read the TypeLib of the COM library and then generate Java wrapper classes for hidding all those unmanageable code.
I'm a newbie in the COM world, so I don't know how to obtain the information about interfaces, methods and parameters that describe a COM object. I read about something called TypeLib, but I don't know how to read it. How can I obtain information from it?
The official API is available here: Type Description Interfaces.
You can use it from C++ directly but I suggest you use .NET (C# in my sample) with an extra tool that Microsoft has written long time ago (mine is dated 1997), named TLBINF32.DLL. It's also a COM object but is Automation (VBScript, Javascript, VB/VBA) and .NET compatible.
You can find TLBINF32.DLL googling for it (this link seems to work today: tlbinf32.dll download, make sure you get the .ZIP file, not what they call the "fixer"...). Note it's a 32-bit DLL so your program must be compiled as 32-bit to be able to use it. I don't know of any 64-bit version but how to use it a with 64-bit client is described here: tlbinf32.dll in a 64bits .Net application
How to use this library is explained in detail here in this december 2000 MSDN magazine's article: Inspect COM Components Using the TypeLib Information Object Library. It's VB (not .NET) oriented, but it's quite easy to translate in .NET terms.
Here is a sample console app in C# that just dumps all type info from a type lib (here MSHTML.TLB):
class Program
{
static void Main(string[] args)
{
TypeLibInfo tli = new TypeLibInfo();
tli.ContainingFile = #"c:\windows\system32\mshtml.tlb";
foreach (TypeInfo ti in tli.TypeInfos)
{
Console.WriteLine(ti.Name);
// etc...
}
}
}
In my own program I'm trying to use this code here to add tooltip balloon windows to my application: http://www.codeproject.com/Articles/4991/Balloon-Tips-Galore (Source code available here)
I tried compiling the demo program and it works fine on 32-bit Windows 7, but when I try to use it on 64-bit Windows 7 the program crashes. If I try to debug the crash in VS2010 I get this message:
The debugger is in some area where the source code isn't available and it says Call stack location: ntdll.dll!0000000076fe40f2()
How can I fix this so it won't crash on 64-bit?
I can't make the C# demo crash on Windows Server 2003 x64 (which is the only 64-bit environment I have handy at the moment), but the code is faulty so it makes sense that you're seeing unexpected behavior.
Edit: Reproduced the crash in Windows Server 2008 R2 x64 using the original code, and verified the efficacy of the fix.
As Christian.K points out, the problem has been noted before. When calling the Marshal.StructureToPtr method, you should pass true for the third fDeleteOld parameter only when the specified memory block does not contain valid data. This is called out pretty explicitly in the documentation, so I'm not sure how the original writer got it wrong.
In this case, since the data was just allocated the line before by calling Marshal.AllocHGlobal, it does not contain valid data and should not be deleted/freed. The change is simple: change the third parameter true to false. Unfortunately, because the interop code is scattered across three different classes in the sample project, you'll have to make the change multiple places. The pattern you're looking for is this:
IntPtr ptrStruct = Marshal.AllocHGlobal(Marshal.SizeOf(ti));
Marshal.StructureToPtr(ti, ptrStruct, false /* <-- change this from true to false */);
Just as a general observation: the code tries to handle a lot of the interop stuff manually (by using methods of the Marshal class) rather than just letting the CLR handle it automatically. I much prefer the latter method. Even though I fully understand how to do all of the interop manually, letting the system manage it for me keeps down the number of mistakes I make and resulting heap corruption.
RhysW says he's never encountered heap corruption before, but it becomes very common when you start doing interop between .NET code and the Win32 API. The .NET Framework is no longer protecting you.
For an example of what I mean, notice that the FMSBalloonTip.SetToolTip method uses the Marshal.StringToHGlobalAuto method to marshal the string containing the tooltip's title as a pointer. While that certainly works (and the author was thankfully careful to free the pointer after they're finished), it would be much easier and less error-prone to declare an overload of the SendMessage function that accepts a string object as the fourth parameter. That way, the framework will handle all of the necessary interop stuff for you transparently.
The real question, of course, is why you need this code at all. It's way easier to just use the built-in ToolTip class, which has been available since the beginning. I'm not sure if you just didn't mention some feature you need that ToolTip doesn't provide or you just don't know about it, but I strongly recommend reconsidering your design so that you can make use of the built-in class and let the Microsoft programmers handle all of the interop stuff.
If it's the balloon part you're looking for, make sure to set the IsBalloon property of the ToolTip class. That wasn't introduced until .NET 2.0, but that's the same version the sample project is targeting.
I want to create a .NET CF application for Windows Mobile 5. In this application, I want to load a COM object based on the ProgID (or CLSID).
How do I load this COM object in such a way that I can access its methods as if it were just another .NET object?
In addition: how can I configure the projects / solutions in Visual Studio in such a way, that when I debug the application, I am sure that the COM object that is loaded is the one that is installed on the device, not one that may be accessible through the debugger?
I have tried adding the .ocx file as a Reference, but I get an error, and I am not sure about 'question 2'. I have also tried loading the COM object using
Type type = Type.GetTypeFromProgID("my.prog.id")
MyObject myObject = (MyObject)Activator.CreateInstance(type)
...but this results in an InvalidCastException on the second line.
EDIT: For the record: I am working on a 64-bit Windows 7 machine, not sure if this complicates things...
You need a runtime callable wrapper (RCW). See this MSDN article for the basics. For more complex things like ActiveX controls, see this article.
Writing some test scripts in IronPython, I want to verify whether a window is displayed or not. I have the pid of the main app's process, and want to get a list of window titles that are related to the pid.
I was trying to avoid using win32api calls, such as FindWindowEx, since (to my knowledge) you cannot access win32api directly from IronPython. Is there a way to do this using built-in .net classes? Most of the stuff I have come across recommends using win32api, such as below.
.NET (C#): Getting child windows when you only have a process handle or PID?
UPDATE: I found a work-around to what I was trying to do. Answer below.
As of IronPython 2.6 the ctypes module is supported. This module provides C compatible data types, and allows calling functions in DLLs. Quick example:
import ctypes
buffer = ctypes.create_string_buffer(100)
ctypes.windll.kernel32.GetWindowsDirectoryA(buffer, len(buffer))
print buffer.value
The article below shows how to access the win32api indirectly from IronPython. It uses CSharpCodeProvider CompileAssemblyFromSource method to compile an assembly in memory from the supplied C# source code string. IronPython can then import the assembly.
Dynamically compiling C# from IronPython
It's like asking if you can swim without going in to the water. If you need information from windows, the only option is to use the win32api. There are lots of examples to find on how to do so.
If you don't like this answer, just leave a comment in your question and I will remove this answer, so your question will remain in the unanswered questions list.