Detect Server Display Resolution - c#

On windows server 2008 can I have a web service or something I can query from a C# application as to the display properties (resolution (height & width)). The C# application does not run on the server so I cannot just detect it from the application itself.
Addition to help explain why:
I will have a user named "display" and that will be logged on displaying a website (on the server) and I want to be able to check the display from the desktop application so the user knows what resolution to design a template for. The resolution will change from different displays so it can't be a set value.

I'd recommend just querying the server using WMI. Check the third example here:
http://msdn.microsoft.com/en-us/library/aa394591%28v=vs.85%29.aspx

My Code
This is the code that I used to solve the problem:
System.Management.ConnectionOptions oConnectionOptions = new System.Management.ConnectionOptions();
{
oConnectionOptions.Username = ServerManagement.GetServerUser();
oConnectionOptions.Password = ServerManagement.GetServerPassword();
}
ManagementPath oPath = new ManagementPath("\\\\" + ServerManagement.GetServerAddress() + "\\root\\cimv2");
ManagementScope oScope = new ManagementScope(oPath, oConnectionOptions);
try
{
oScope.Connect();
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DesktopMonitor");
ManagementObjectCollection obj = searcher.Get();
foreach (ManagementObject service in obj)
{
this.DisplayHeight = Convert.ToInt16(service["ScreenHeight"]);
this.DisplayWidth = Convert.ToInt16(service["ScreenWidth"]);
}
}
catch (Exception)
{
MessageBox.Show("Cannot connect to server, please try again later.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}

Related

Unable to format a drive using ManagementObject from Non-Admin account

I have below code to format a USB drive. Code works fine with Admin account, but if I run the exe using Non Admin account, it returns 3 (Access Denied).
I want to format a drive in Non-Admin mode. Any help?
I visited this link https://social.msdn.microsoft.com/Forums/en-US/1e192745-9d58-4507-93f0-ceacbc0cde96/wmi-win32volume-format-method-returns-access-denied?forum=windowsgeneraldevelopmentissues , but no help
ManagementObjectSearcher searcher = new ManagementObjectSearcher(#"select * from Win32_Volume WHERE DriveLetter = '" + driveLetter + "'");
foreach (ManagementObject vi in searcher.Get())
{
var result = vi.InvokeMethod("Format", new object[] { fileSystem, quickFormat, clusterSize, label, enableCompression });
if (Convert.ToInt32(result) != 0)
{
throw new Exception("Error while formating drive");
}
}
Have you tried "Right Click> Compatibility> Change All User Settings> Run As Administrator"?
If this is the solution, you can do this with the code.
Probably, this question - answer, can answer your problem.
How do I force my .NET application to run as administrator?

Simple C# WMI Get & Put

I am trying to Read & Put values from and to WMI using C#.
The current example uses ccm namespace, for configmgr client.
The read functions works correctly, able to read ADV_RepeatRunBehavior value.
Though the Put(); doesn't work as expected, the values are not stored back and Invalid Class exception is thrown.
Some advice would be nice as I am new to this, many thanks.
static void Main(string[] args)
{
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher(
"root\\ccm\\Policy\\Machine",
"SELECT * FROM CCM_SoftwareDistribution WHERE PKG_PackageID='XXXXXXXX'");
foreach (ManagementObject queryObj in searcher.Get())
{
//Read works
//Console.WriteLine(queryObj["ADV_RepeatRunBehavior"].ToString());
//Console.ReadLine();
//Put doesn't
queryObj["ADV_RepeatRunBehavior"] = "RerunNever";
queryObj.Put();
}
}
catch (ManagementException z)
{
Console.WriteLine("An error occurred: " + z.Message);
Console.ReadLine();
}
}
Found the resolution for this.
You have to run Visual Studio as Administrator if testing on localhost
The connection to WMI has to be \\root\\ccm\\Policy\\Machine\\ActualConfig then its possible to Put() values.

Renaming Printer using C# and WMI

I have created a C# application to rename printers on a Citrix server (Server 2008 R2).
The reason for this is because every time a user logs on the printer gets forwarded to the server and gets a unique name(For example Microsoft XPS Document Writer (from WI_UFivcBY4-wgoYOdlQ) in session 3) and from within some applications thats an issue since the printer is pointed to the name and by that you need to change the printer setting everytime you logon a session.
The program itself works like a charm and the printer gets the names I desire.
However the issue is after that the printers have been renamed Windows does not seem to be able to identify them anymore. For example if I try to change default printer i get an error saying "Error 0x00000709 Double check the printer name and make sure that the printer is connected to the network."
var query = new ManagementObjectSearcher("SELECT * FROM Win32_Printer where name like '%(%'");
ManagementObjectCollection result = query.Get();
foreach (ManagementObject printer in result)
{
string printerName = printer["name"].ToString();
if (printerName.IndexOf('(') > 0)
{
printer.InvokeMethod("RenamePrinter", new object[] { printerName.Substring(0, printerName.IndexOf('(')).Trim() + " " + userName }); //userName is provided as an inputparameter when running the application
}
}
Am I missing anything? Are there anything else i need to do when renaming?
I cant seem to find any info regarding this case at all.
i thing this codeproject is what your looking for. But after some own experiences with the printers in C# i can only say it does not make fun and it can be really frustrating
Code with small modifications:
//Renames the printer
public static void RenamePrinter(string sPrinterName, string newName)
{
ManagementScope oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
oManagementScope.Connect();
SelectQuery oSelectQuery = new SelectQuery();
oSelectQuery.QueryString = #"SELECT * FROM Win32_Printer WHERE Name = '" + sPrinterName.Replace("\\", "\\\\") + "'";
ManagementObjectSearcher oObjectSearcher =
new ManagementObjectSearcher(oManagementScope, oSelectQuery);
ManagementObjectCollection oObjectCollection = oObjectSearcher.Get();
if (oObjectCollection.Count == 0)
return;
foreach (ManagementObject oItem in oObjectCollection)
{
int state = (int)oItem.InvokeMethod("RenamePrinter", new object[] { newName });
switch (state)
{
case 0:
//Success do noting else
return;
case 1:
throw new AccessViolationException("Access Denied");
case 1801:
throw new ArgumentException("Invalid Printer Name");
default:
break;
}
}
}
Still works great in 2022, thank you. Just had to change type
int
to
UInt32
to avoid new Exception:
UInt32 state = (UInt32)oItem.InvokeMethod("RenamePrinter", new object[] { newName });
switch (state)
{...

How to list all local computer user profiles in a combo box?

I need to enumerate all user profiles on a local computer and list them in a combo box. Any special accounts need to be filtered out. I'm only concerned about actual user profiles on the computer where the app is running. I have done some searching but I haven't found a clear answer posted anywhere. I did find some code that might work but SelectQuery and ManagementObjectSearcher are displaying errors in VS and I'm not sure what I need to do to make this work.
using System.Management;
SelectQuery query = new SelectQuery("Win32_UserAccount");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject envVar in searcher.Get())
{
Console.WriteLine("Username : {0}", envVar["Name"]);
}
By saying "SelectQuery and ManagementObjectSearcher are displaying errors" I guess you didn't reference the System.Management dll.
You should right click References in your solution and add System.Management.
Then, with your using statement, the errors should disappear.
Anyway, including the error next time will assist everyone to help you :)
The mentioned code is great but when I tried on a machine connected to a Active Directory Domain all the usernames where returned for the domain. I was able to tweak the code a bit to only return the users that actually have a local directory on the current machine. If a better C# developer can refactor the code to make it cleaner - please help!
var localDrives = Environment.GetLogicalDrives();
var localUsers = new List<string>();
var query = new SelectQuery("Win32_UserAccount") { Condition = "SIDType = 1 AND AccountType = 512" };
var searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject envVar in searcher.Get())
{
foreach (string drive in localDrives)
{
var dir = Path.Combine(String.Format("{0}Users", drive), envVar["name"].ToString());
if (Directory.Exists(dir))
{
localUsers.Add(envVar["name"].ToString());
}
}
}
Once you have the localUsers variable you can set this as the data source to your ComboBox control of our choice.

How do I retrieve the username that a Windows service is running under?

Given a service name, I would like to retrieve the username that it runs under (i.e. the username shown in the 'Log On' tab of a service's properties window).
There doesn't appear to be anything in the ServiceController class to retrieve this basic information. Nothing else in System.ServiceProcess looks like it exposes this information either.
Is there a managed solution to this, or am I going to have to drop down into something lower-level?
Using WMI, with the System.Management you can try the following code:
using System;
namespace WindowsServiceTest
{
class Program
{
static void Main(string[] args)
{
System.Management.SelectQuery sQuery = new System.Management.SelectQuery(string.Format("select name, startname from Win32_Service")); // where name = '{0}'", "MCShield.exe"));
using (System.Management.ManagementObjectSearcher mgmtSearcher = new System.Management.ManagementObjectSearcher(sQuery))
{
foreach (System.Management.ManagementObject service in mgmtSearcher.Get())
{
string servicelogondetails =
string.Format("Name: {0} , Logon : {1} ", service["Name"].ToString(), service["startname"]).ToString();
Console.WriteLine(servicelogondetails);
}
}
Console.ReadLine();
}
}
}
You can then later substitute the commented code with your service name, and it should only return the instances of your service process that is running.
WMI is your friend. Look at Win32_Service, specifically the StartName property. You can access WMI from C# via the System.Management.ManagementClass.
If you've not used WMI before, this article seems to be quite a good tutorial.
You can find this using the Windows Registry, reading the following string value, replacing [SERVICE_NAME] with the name of the Windows Service:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\[SERVICE_NAME]\ObjectName
Try this:
System.Security.Principal.WindowsIdentity.GetCurrent();
but the most obvious you will get LOCAL SYSTEM or NETWORK. The reason that you cannot show this user - that service can manage multiple users (shared by desktop, attached to current windows session, using shared resource ...)
System starts service, but any user can use it.
This solution works fine for me:
ManagementObject wmiService = new ManagementObject("Win32_Service.Name='" + this.ServiceName + "'");
wmiService.Get();
string user = wmiService["startname"].ToString();
public String getUsername() {
string username = null;
try {
ManagementScope ms = new ManagementScope("\\\\.\\root\\cimv2");
ms.Connect();
ObjectQuery query = new ObjectQuery
("SELECT * FROM Win32_ComputerSystem");
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(ms, query);
foreach (ManagementObject mo in searcher.Get()) {
username = mo["UserName"].ToString();
}
string[] usernameParts = username.Split('\\');
username = usernameParts[usernameParts.Length - 1];
} catch (Exception) {
username = "SYSTEM";
}
return username;
}

Categories