Accessing custom WMI provider hangs indefinitely - c#

I'm trying to write a custom decoupled WMI provider in C#. I've followed the examples and yet whenever I try to access my WMI class from either WMI Studio, through PowerShell, or via wmic, it just hangs there indefinitely until I terminate the provider host app, at which point I get an error ranging from "Invalid Class" to "The remote procedure call failed".
I can see my WMI provider fine if I don't try to actually access an instance of it, so I know it's registering with WMI.
Here's the code I'm running:
[assembly: WmiConfiguration(#"root\CIMV2", HostingModel=ManagementHostingModel.Decoupled)]
[RunInstaller(true)]
public class WmiInstaller : DefaultManagementInstaller { }
[ManagementEntity(Singleton=true)]
[ManagementQualifier("Description", Value="Accesses and manipulates licenses held in the SLN license database.")]
public class SoftwareLicensingNetworkLicenseDatabase {
[ManagementBind]
public SoftwareLicensingNetworkLicenseDatabase() { Test = "OMG!"; }
[ManagementProbe]
public string Test;
}
And then in my main function:
[STAThread]
static void Main() {
InstrumentationManager.RegisterType(typeof(SoftwareLicensingNetworkLicenseDatabase));
Console.ReadLine();
InstrumentationManager.UnregisterType(typeof(SoftwareLicensingNetworkLicenseDatabase));
}
I've tried any number of things to diagnose this issue: switch to .Net 3.5 (I'm using .Net 4.0), change namespace names, use a multi-instance class instead of a singleton, etc.
Any help would be sincerely appreciated!

Nevermind, I figured it out:
Your Main function cannot have STAThread as an attribute. I added it when I was debugging something that required it and had not taken it off. It figures it would take me so long to figure out something so simple and obvious once you think about it.

Related

How to sandbox code running another app (started using Process.Start)?

I've heard of sandboxing and how to make a simple example using AppDomain in .NET as in this article https://learn.microsoft.com/en-us/dotnet/framework/misc/how-to-run-partially-trusted-code-in-a-sandbox
However the unsafe (or untrusted) code I execute here is run another process using Process.Start (or if you know another way to help limit access of the started process, please suggest). My purpose is to constrain resource access of the started process (may not be a .NET app). So for example, the started process should not be able to access any file in the current environment.
The issue here is we need a security context (provided by the current AppDomain) having full-trust (unrestricted) for Process.Start to work.
I really hope that the current partially-trusted context (before calling Process.Start) would be cascaded down to the started process and can help constrain the resource access as expected. But if we need a full-trust context to run Process.Start, then it fails right at that step.
I've run out of ideas for how to make this possible because the only way I know to run a process in .NET is using Process.Start but it requires full-trust context … :(
Here is the code I've tried and there is always an error being thrown right before calling Process.Start:
class Program
{
static void Main(string[] args)
{
var ads = new AppDomainSetup();
ads.ApplicationBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var ps = new PermissionSet(System.Security.Permissions.PermissionState.None);
ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
var ad = AppDomain.CreateDomain("SB", null, ads, ps);
var sb = ad.CreateInstanceAndUnwrap(typeof(Sandbox).Assembly.FullName, typeof(Sandbox).FullName) as Sandbox;
//the code throws exception and be highlighted at this line
sb.ExecuteUnsafeCode();
Console.WriteLine("End!");
Console.ReadLine();
}
}
//the sandbox class
public class Sandbox : MarshalByRefObject
{
//this simple method stub is just for testing
public void ExecuteUnsafeCode()
{
try
{
var si = new ProcessStartInfo("someSimpleApp.exe");
Process.Start(si);
Console.WriteLine("Run OK!");
} catch(Exception ex)
{
Console.WriteLine("SecurityException caught:\n{0}", ex.ToString());
}
}
}
The exception thrown is a SecurityException with a very short message of Request fail. The stack-trace is also too short (only 3 lines) and actually contains nothing helpful.
The bigger picture of my purpose here is to run submitted code (from user) in a sandbox so that no malicious code can harm the server. If the submitted code is some .NET lang, it would be easier because I may not have to use Process.Start here. But the submitted code is Java or unmanaged C++, really we have to compile it into some executable file and run it using Process.Start.
I hope to get some suggestions to try out, of course it's better if I have a right solution for this, thanks!

How to use ApprovalTests on Teamcity?

I am using Approval Tests. On my dev machine I am happy with DiffReporter that starts TortoiseDiff when my test results differ from approved:
[UseReporter(typeof (DiffReporter))]
public class MyApprovalTests
{ ... }
However when the same tests are running on Teamcity and results are different tests fail with the following error:
System.Exception : Unable to launch: tortoisemerge.exe with arguments ...
Error Message: The system cannot find the file specified
---- System.ComponentModel.Win32Exception : The system cannot find the file
specified
Obviously it cannot find tortoisemerge.exe and that is fine because it is not installed on build agent. But what if it gets installed? Then for each fail another instance of tortoisemerge.exe will start and nobody will close it. Eventually tons of tortoisemerge.exe instances will kill our servers :)
So the question is -- how tests should be decorated to run Tortoise Diff on local machine
and just report errors on build server? I am aware of #IF DEBUG [UseReporter(typeof (DiffReporter))] but would prefer another solution if possible.
There are a couple of solutions to the question of Reporters and CI. I will list them all, then point to a better solution, which is not quite enabled yet.
Use the AppConfigReporter. This allows you to set the reporter in your AppConfig, and you can use the QuietReporter for CI.
There is a video here, along with many other reporters. The AppConfigReporter appears at 6:00.
This has the advantage of separate configs, and you can decorate at the assembly level, but has the disadvantage of if you override at the class/method level, you still have the issue.
Create your own (2) reporters. It is worth noting that if you use a reporter, it will get called, regardless as to if it is working in the environment. IEnvironmentAwareReporter allows for composite reporters, but will not prevent a direct call to the reporter.
Most likely you will need 2 reporters, one which does nothing (like a quiet reporter) but only works on your CI server, or when called by TeamCity. Will call it the TeamCity Reporter. And One, which is a multiReporter which Calls teamCity if it is working, otherwise defers to .
Use a FrontLoadedReporter (not quite ready). This is how ApprovalTests currently uses NCrunch. It does the above method in front of whatever is loaded in your UseReporter attribute. I have been meaning to add an assembly level attribute for configuring this, but haven't yet (sorry) I will try to add this very soon.
Hope this helps.
Llewellyn
I recently came into this problem myself.
Borrowing from xunit and how they deal with TeamCity logging I came up with a TeamCity Reporter based on the NCrunch Reporter.
public class TeamCityReporter : IEnvironmentAwareReporter, IApprovalFailureReporter
{
public static readonly TeamCityReporter INSTANCE = new TeamCityReporter();
public void Report(string approved, string received) { }
public bool IsWorkingInThisEnvironment(string forFile)
{
return Environment.GetEnvironmentVariable("TEAMCITY_PROJECT_NAME") != null;
}
}
And so I could combine it with the NCrunch reporter:
public class TeamCityOrNCrunchReporter : FirstWorkingReporter
{
public static readonly TeamCityOrNCrunchReporter INSTANCE =
new TeamCityOrNCrunchReporter();
public TeamCityOrNCrunchReporter()
: base(NCrunchReporter.INSTANCE,
TeamCityReporter.INSTANCE) { }
}
[assembly: FrontLoadedReporter(typeof(TeamCityOrNCrunchReporter))]
I just came up with one small idea.
You can implement your own reporter, let's call it DebugReporter
public class DebugReporter<T> : IEnvironmentAwareReporter where T : IApprovalFailureReporter, new()
{
private readonly T _reporter;
public static readonly DebugReporter<T> INSTANCE = new DebugReporter<T>();
public DebugReporter()
{
_reporter = new T();
}
public void Report(string approved, string received)
{
if (IsWorkingInThisEnvironment())
{
_reporter.Report(approved, received);
}
}
public bool IsWorkingInThisEnvironment()
{
#if DEBUG
return true;
#else
return false;
#endif
}
}
Example of usage,
[UseReporter(typeof(DebugReporter<FileLauncherReporter>))]
public class SomeTests
{
[Test]
public void test()
{
Approvals.Verify("Hello");
}
}
If test is faling, it still would be red - but reporter would not came up.
The IEnvironmentAwareReporter is specially defined for that, but unfortunatelly whatever I return there, it still calls Report() method. So, I put the IsWorkingInThisEnvironment() call inside, which is a little hackish, but works :)
Hope that Llywelyn can explain why it acts like that. (bug?)
I'm using CC.NET and I do have TortoiseSVN installed on the server.
I reconfigured my build server to allow the CC.NET service to interact with the desktop. When I did that, TortiseMerge launched. So I think what's happening is that Approvals tries to launch the tool, but it cant because CC.NET is running as a service and the operating system prevents that behavior by default. If TeamCity runs as a service, you should be fine, but you might want to test.

DLL containing custom attribute remains locked

I am trying to write an attribute to apply security to a method. Something that would look like this:
[CustomAuthorization(SecurityAction.Demand)]
public void DoSomething()
{
//Do Something
}
so I have my Attribute on another assembly:
public sealed class AuthorizationAttribute : CodeAccessSecurityAttribute
{
public override IPermission CreatePermission()
{
if (!/*authorize here*/)
{
return new CustomPermission(PermissionState.Unrestricted);
}
throw new Exception("IdentificationFailure.");
}
}
public AuthorizationAttribute(SecurityAction securityAction)
: base(securityAction) { }
}
So far it works.
I run my main program and it does its job.
Now I go and to modify the assembly having the attribute, build it. no problem.
I go back in my main program try to build and there it fails. It cannot copy the new built dll because the old one is still in use by a process.
Does anybody have any idea what would be happening here?
If you're using VS2010, there is an issue with vhost.exe not releasing the instance. You can end process on it for now until MS comes out with a fix.
It sounds like you haven't exited your main program before trying to rebuild it. Check your running processes for references to your main program or your security attribute dll. Process Explorer can be a real big help here.
Just been trouble shooting the same issue and it boiled down to the fact that we were using testaccessors to test private methods. When unloading the unittest projects, the assembly is released. Our assembly gets locked when compiling. Haven't found a solution to this yet, but have submitted a bug to ms. Are you using testaccessors?
Also see Assembly is being used by another process and https://stackoverflow.com/questions/6895038/testaccessor-impl-of-codeaccesssecurityattribute-locks-assembly
MS bug:
https://connect.microsoft.com/VisualStudio/feedback/details/682485/use-of-testaccessor-and-impl-of-codeaccesssecurityattribute-locks-assembly#details

How to implement single instance per machine application?

I have to restrict my .net 4 WPF application so that it can be run only once per machine. Note that I said per machine, not per session.
I implemented single instance applications using a simple mutex until now, but unfortunately such a mutex is per session.
Is there a way to create a machine wide mutex or is there any other solution to implement a single instance per machine application?
I would do this with a global Mutex object that must be kept for the life of your application.
MutexSecurity oMutexSecurity;
//Set the security object
oMutexSecurity = new MutexSecurity();
oMutexSecurity.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), MutexRights.FullControl, AccessControlType.Allow));
//Create the global mutex and set its security
moGlobalMutex = new Mutex(True, "Global\\{5076d41c-a40a-4f4d-9eed-bf274a5bedcb}", bFirstInstance);
moGlobalMutex.SetAccessControl(oMutexSecurity);
Where bFirstInstance returns if this is the first instance of your application running globally. If you omited the Global part of the mutex or replaced it with Local then the mutex would only be per session (this is proberbly how your current code is working).
I believe that I got this technique first from Jon Skeet.
The MSDN topic on the Mutex object explains about the two scopes for a Mutex object and highlights why this is important when using terminal services (see second to last note).
I think what you need to do is use a system sempahore to track the instances of your application.
If you create a Semaphore object using a constructor that accepts a name, it is associated with an operating-system semaphore of that name.
Named system semaphores are visible throughout the operating system, and can be used to synchronize the activities of processes.
EDIT: Note that I am not aware if this approach works across multiple windows sessions on a machine. I think it should as its an OS level construct but I cant say for sure as i havent tested it that way.
EDIT 2: I did not know this but after reading Stevo2000's answer, i did some looking up as well and I think that the "Global\" prefixing to make the the object applicable to the global namespace would apply to semaphores as well and semaphore, if created this way, should work.
You could open a file with exclusive rights somewhere in %PROGRAMDATA%
The second instance that starts will try to open the same file and fail if it's already open.
How about using the registry?
You can create a registry entry under HKEY_LOCAL_MACHINE.
Let the value be the flag if the application is started or not.
Encrypt the key using some standard symmetric key encryption method so that no one else can tamper with the value.
On application start-up check for the key and abort\continue accordingly.
Do not forget to obfuscate your assembly, which does this encryption\decryption part, so that no one can hack the key in registry by looking at the code in reflector.
I did something similar once.
When staring up the application list, I checked all running processes for a process with identical name, and if it existed I would not allow to start the program.
This is not bulletproof of course, since if another application have the exact same process name, your application will never start, but if you use a non-generic name it will probably be more than good enough.
For the sake of completeness, I'd like to add the following which I just found now:
This web site has an interesting approach in sending Win32 messages to other processes. This would fix the problem of the user renaming the assembly to bypass the test and of other assemblies with the same name.
They're using the message to activate the main window of the other process, but it seems like the message could be a dummy message only used to see whether the other process is responding to it to know whether it is our process or not.
Note that I haven't tested it yet.
See below for full example of how a single instace app is done in WPF 3.5
public class SingleInstanceApplicationWrapper :
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{
public SingleInstanceApplicationWrapper()
{
// Enable single-instance mode.
this.IsSingleInstance = true;
}
// Create the WPF application class.
private WpfApp app;
protected override bool OnStartup(
Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
app = new WpfApp();
app.Run();
return false;
}
// Direct multiple instances.
protected override void OnStartupNextInstance(
Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e)
{
if (e.CommandLine.Count > 0)
{
app.ShowDocument(e.CommandLine[0]);
}
}
}
Second part:
public class WpfApp : System.Windows.Application
{
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
WpfApp.current = this;
// Load the main window.
DocumentList list = new DocumentList();
this.MainWindow = list;
list.Show();
// Load the document that was specified as an argument.
if (e.Args.Length > 0) ShowDocument(e.Args[0]);
}
public void ShowDocument(string filename)
{
try
{
Document doc = new Document();
doc.LoadFile(filename);
doc.Owner = this.MainWindow;
doc.Show();
// If the application is already loaded, it may not be visible.
// This attempts to give focus to the new window.
doc.Activate();
}
catch
{
MessageBox.Show("Could not load document.");
}
}
}
Third part:
public class Startup
{
[STAThread]
public static void Main(string[] args)
{
SingleInstanceApplicationWrapper wrapper =
new SingleInstanceApplicationWrapper();
wrapper.Run(args);
}
}
You may need to add soem references and add some using statements but it shoudl work.
You can also download a VS example complete solution by downloading the source code of the book from here.
Taken From "Pro WPF in C#3 2008 , Apress , Matthew MacDonald" , buy the book is gold. I did.

How to detect C# project type and / or how to detect Console availability

I have two Windows services written in C#. One service is "Console Application" and second one is "Windows Application" (can't change it).
Both service applications can be executed in few modes (depending on command line arguments and Environment.UserInteractive flag):
when (Environment.UserInteractive == false) and...
when no cmd-line parameter is provided - standard out-generated code (required for SCM) is executed - ServiceBase.Run(ServicesToRun)
when (Environment.UserInteractive == true) and...
when "-i" cmd-line parameter is provided - service application installs itself (something like installutil -i [scv_app])
when "-u" cmd-line parameter is provided - service application uninstalls itself (something like installutil -u [scv_app])
when "-c" cmd-line parameter is provided - service is executed in "console" mode (for debug purposes)
Both services use static method from class library to choose and process described execution path.
However, I have one problem in this class library - when application has type "Windows Application", then Console.WriteLine() has no visible effect. In that case I could use Win32 AttachConsole() or something like that, but I prefer to show summarized messages via MessageBox.Show().
Thus, I think that in class library I need to know whether application is "Console Application" or "Windows Application"... Do you have any idea how to do it?
At the beginning, instead of trying to detect app type I have tried to write something like that:
if (string.IsNullOrEmpty(Console.Title) == false) Console.WriteLine(msg);
It works in Win7 but it does not work under Win2k3. So maybe there is a better way to detect if Console.WriteLine(msg) / Console.ReadLine works as expected?
I’ve seen some other suggestions (sublinked here), but none of them looks good to me. I am looking for "nice" solution (!= p/invoke; != accessing any Console object property (e.g. Title) inside a try/catch block).
Windows services are not supposed to have ui. This includes consoles and messageboxes.
With that out of the way...
Have you considered hooking up an appropriate trace listener to System.Diagnostics.Trace.TraceListeners? Based on your command line you could add a MessageBox tracelistener or a tracelistener that dumps trace messages to a console? You'll be leveraging built-in debugging mechanisms that have been extensively tested and are, in their own way, extremely extensible as well. You'll also implicitly get to distinguish between messages that are displayed in release mode vs. messages displayed in debug mode (via System.Diagnostics.Trace.Write() or System.Diagnostics.Debug.Write()).
The when dealing with a class library, I pass in a UI object depending on the environment that is calling the library.
public interface IAlerts {
void Show(string message);
}
public class EventLogAlerts : IAlerts { ... }
public class WindowsAlerts : IAlerts { ... }
public class ConsoleAlerts : IAlerts { ... }
public class MyLibrary {
private IAlerts alertImpl = new EventLogAlerts();
public void SetUserInterface(IMyUserInterface impl)
{
this.alertImpl = impl;
}
public void DoSomething()
{
try
{
...
}
catch (Exception)
{
this.alertImpl.Show("Whoops!");
}
}
}

Categories