0

I would like to make a report from msinfo32 command to a nfo file in user's desktop folder. I run this exe directly because command msinfo32 sometimes is not in XP's PATH. So, this is what I would like from C#:

"C:\Program Files\Common Files\Microsoft Shared\MSInfo\msinfo32.exe" /nfo C:\Users\someUser\Desktop\my_pc.nfo

I have this code for now, it calls UAC and then the cmd window closes. The file is not created. Why is this not working?

        var proc1 = new ProcessStartInfo();

        string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        string myFile = "my_pc.nfo";
        string myFullPath = Path.Combine(desktopPath, myFile);
        string myCommand = @"/C C:\Program Files\Common Files\Microsoft Shared\MSInfo\msinfo32.exe /nfo " + myFullPath;

        proc1.UseShellExecute = true;
        proc1.WorkingDirectory = @"C:\Windows\System32";
        proc1.FileName = @"C:\Windows\System32\cmd.exe";
        proc1.Verb = "runas";

        char quote = '"';
        proc1.Arguments = "/C " + quote + myCommand + quote;
        proc1.WindowStyle = ProcessWindowStyle.Normal;
        Process.Start(proc1);

        Console.ReadLine();
Hrvoje T
  • 3,365
  • 4
  • 28
  • 41
  • would it not be possible to call msinfo32.exe directly, without the cmd.exe call in between? I think it is not possible to chain calls and preserve the arguments. the /nfo argument will become an argument of the cmd.exe call and go missing for the msinfo32 "sub"-call. – Cee McSharpface Sep 20 '18 at 06:36
  • The must find out whether the process completed successfully, use the ExitCode property. If it is not 0 then it failed. A large negative value tends to be useful to diagnose an exception. – Hans Passant Sep 20 '18 at 07:36

2 Answers2

1

NB: MSInfo doesn't set an errorlevel.

Your MSINFO32 command line doesn't quote the saved filename. So if it contains spaces it won't work.

For a completely unknown reason you are calling CMD even though you don't want it to do anything.

You are using a unsupported way to elevate, it only works if the configuration of exe file association hasn't been changed. You use a manifest to elevate. See Run batch script as admin during Maven build

Also see wmi as a program should be doing. You can experiment with wmic command line tool. Programs are for users not other programs.

This is looking for wifi networks

Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")

Set colItems = objWMIService.ExecQuery("Select * From WiFi_AvailableNetwork")
'msgbox colitems
For Each objItem in colItems
    msgbox objItem.name & " " & objItem.Description
Next

This list services,

Set objWMIService = GetObject("winmgmts:\\127.0.0.1\root\cimv2")

Set config = objWMIService.ExecQuery("Select * From Win32_Service")
For Each thing in Config
        Msgbox thing.Caption
Next

Monitors

Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")

Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor")

For Each objItem in colItems
    msgbox  objItem.Model & " " & objItem.Manufacturer & " " & objItem.SerialNumber
Next

This waits for power events to occur and either kills or starts calculator.

Set colMonitoredEvents = GetObject("winmgmts:")._
    ExecNotificationQuery("SELECT * FROM Win32_PowerManagementEvent")
Do
    Set strLatestEvent = colMonitoredEvents.NextEvent
    If strLatestEvent.EventType = 4 Then 
        Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
        Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
        For Each objItem in colItems
            If objItem.name = "Calculator.exe" then objItem.terminate
        Next
    ElseIf strLatestEvent.EventType = 7 Then 
        wscript.sleep 2000
        Set WshShell = WScript.CreateObject("WScript.Shell")
        WshShell.Run "calc.exe", 1, false
    End If
Loop
CatCat
  • 483
  • 4
  • 5
  • Thanks for a manifest file. I added it from VS like here https://stackoverflow.com/questions/2818179/how-do-i-force-my-net-application-to-run-as-administrator .I'm beginner in C#, don't know VB nor wmic. Thanks anyway. – Hrvoje T Sep 25 '18 at 11:03
0

From @CatCat's suggestion I managed to run this programm as admin. You'll want to modify the manifest that gets embedded in the program. This works on Visual Studio 2008 and higher: Project + Add New Item, select "Application Manifest File". Change the <requestedExecutionLevel> element to:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

The user gets the UAC prompt when they start the program. I concatenated Enviroment.SpecialFolder.Desktop with my other parameters to an process arugment and now this is working as I wanted.

using System;
using System.Diagnostics;
using System.ServiceProcess;

namespace WinTImeSync
{
    class Program
    {
        static void Main(string[] args)
        {
            if (MsInfoReport() == true)
            {
                Console.WriteLine("Command ran successfully.");
            }
            else
            {
                Console.WriteLine("Did not run.");
            }
            Console.Write("Press any key to continue...");
            Console.ReadKey();
        }

        public static bool MsInfoReport()
        {
            try
            {
                string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                Process processTime = new Process();
                processTime.StartInfo.FileName = @"C:\Program Files\Common Files\microsoft shared\MSInfo\msinfo32.exe";
                processTime.StartInfo.Arguments = "/report " + desktopPath + "\\mypc_info.nfo /categories +systemsummary";
                processTime.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                processTime.Start();
                processTime.WaitForExit();

                return true;
            }
            catch (Exception exception)
            {
                Trace.TraceWarning("unable to run msinfo32", exception);
                return false;
            }
        }
    }
}
Hrvoje T
  • 3,365
  • 4
  • 28
  • 41