I'm looking for a programmatic solution that has the same effect as setting the "Configure Windows NTP Client" state in GPOE Administrative Templates > System > Windows Time Service > Time Providers > Configure Windows NTP Client to Not Configured or Disabled, but I'll take any help I can get at this point.
Is there a registry key I can modify using the .NET Registry class or a property I can modify using the RSoP WMI classes? I've been looking in both places for days, but haven't found anything that will effectively disable the GPO or have the same effect as disabling or setting it to Not Configured in the GUI.
Firstly you have to find the registry value to edit. They are all listed in the XLS document downloadable at http://www.microsoft.com/en-us/download/details.aspx?id=25250. This document does not indicate the type of the value (REGSZ, DWORD, etc), so you have to set the setting by using the editor and then look the type of the value with regedit.
Now you have the registry key, the value name and its type, let's add some C# and use the COM interface IGroupPolicyObject
[ComImport, Guid("EA502722-A23D-11d1-A7D3-0000F87571E3")]
internal class GPClass
{
}
[ComImport, Guid("EA502723-A23D-11d1-A7D3-0000F87571E3"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IGroupPolicyObject
{
uint New([MarshalAs(UnmanagedType.LPWStr)] string domainName, [MarshalAs(UnmanagedType.LPWStr)] string displayName, uint flags);
uint OpenDSGPO([MarshalAs(UnmanagedType.LPWStr)] string path, uint flags);
uint OpenLocalMachineGPO(uint flags);
uint OpenRemoteMachineGPO([MarshalAs(UnmanagedType.LPWStr)] string computerName, uint flags);
uint Save([MarshalAs(UnmanagedType.Bool)] bool machine, [MarshalAs(UnmanagedType.Bool)] bool add, [MarshalAs(UnmanagedType.LPStruct)] Guid extension, [MarshalAs(UnmanagedType.LPStruct)] Guid app);
uint Delete();
uint GetName([MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int maxLength);
uint GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int maxLength);
uint SetDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name);
uint GetPath([MarshalAs(UnmanagedType.LPWStr)] StringBuilder path, int maxPath);
uint GetDSPath(uint section, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder path, int maxPath);
uint GetFileSysPath(uint section, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder path, int maxPath);
uint GetRegistryKey(uint section, out IntPtr key);
uint GetOptions(out uint options);
uint SetOptions(uint options, uint mask);
uint GetType(out IntPtr gpoType);
uint GetMachineName([MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int maxLength);
uint GetPropertySheetPages(out IntPtr pages);
}
public enum GroupPolicySection
{
Root = 0,
User = 1,
Machine = 2,
}
public abstract class GroupPolicyObject
{
protected const int MaxLength = 1024;
/// <summary>
/// The snap-in that processes .pol files
/// </summary>
private static readonly Guid RegistryExtension = new Guid(0x35378EAC, 0x683F, 0x11D2, 0xA8, 0x9A, 0x00, 0xC0, 0x4F, 0xBB, 0xCF, 0xA2);
/// <summary>
/// This application
/// </summary>
private static readonly Guid LocalGuid = new Guid(GetAssemblyAttribute<GuidAttribute>(Assembly.GetExecutingAssembly()).Value);
protected IGroupPolicyObject Instance = null;
static T GetAssemblyAttribute<T>(ICustomAttributeProvider assembly) where T : Attribute
{
object[] attributes = assembly.GetCustomAttributes(typeof(T), true);
if (attributes.Length == 0)
return null;
return (T)attributes[0];
}
internal GroupPolicyObject()
{
Instance = GetInstance();
}
public void Save()
{
var result = Instance.Save(true, true, RegistryExtension, LocalGuid);
if (result != 0)
{
throw new Exception("Error saving machine settings");
}
result = Instance.Save(false, true, RegistryExtension, LocalGuid);
if (result != 0)
{
throw new Exception("Error saving user settings");
}
}
public void Delete()
{
var result = Instance.Delete();
if (result != 0)
{
throw new Exception("Error deleting the GPO");
}
Instance = null;
}
public RegistryKey GetRootRegistryKey(GroupPolicySection section)
{
IntPtr key;
var result = Instance.GetRegistryKey((uint)section, out key);
if (result != 0)
{
throw new Exception(string.Format("Unable to get section '{0}'", Enum.GetName(typeof(GroupPolicySection), section)));
}
var handle = new SafeRegistryHandle(key, true);
return RegistryKey.FromHandle(handle, RegistryView.Default);
}
public abstract string GetPathTo(GroupPolicySection section);
protected static IGroupPolicyObject GetInstance()
{
var concrete = new GPClass();
return (IGroupPolicyObject)concrete;
}
}
public class GroupPolicyObjectSettings
{
public readonly bool LoadRegistryInformation;
public readonly bool Readonly;
public GroupPolicyObjectSettings(bool loadRegistryInfo = true, bool readOnly = false)
{
LoadRegistryInformation = loadRegistryInfo;
Readonly = readOnly;
}
private const uint RegistryFlag = 0x00000001;
private const uint ReadonlyFlag = 0x00000002;
internal uint Flag
{
get
{
uint flag = 0x00000000;
if (LoadRegistryInformation)
{
flag |= RegistryFlag;
}
if (Readonly)
{
flag |= ReadonlyFlag;
}
return flag;
}
}
}
public class ComputerGroupPolicyObject : GroupPolicyObject
{
public readonly bool IsLocal;
public ComputerGroupPolicyObject(GroupPolicyObjectSettings options = null)
{
options = options ?? new GroupPolicyObjectSettings();
var result = Instance.OpenLocalMachineGPO(options.Flag);
if (result != 0)
{
throw new Exception("Unable to open local machine GPO");
}
IsLocal = true;
}
public ComputerGroupPolicyObject(string computerName, GroupPolicyObjectSettings options = null)
{
options = options ?? new GroupPolicyObjectSettings();
var result = Instance.OpenRemoteMachineGPO(computerName, options.Flag);
if (result != 0)
{
throw new Exception(string.Format("Unable to open GPO on remote machine '{0}'", computerName));
}
IsLocal = false;
}
public static void SetPolicySetting(string registryInformation, string settingValue, RegistryValueKind registryValueKind)
{
string valueName;
GroupPolicySection section;
string key = Key(registryInformation, out valueName, out section);
// Thread must be STA
Exception exception = null;
var t = new Thread(() =>
{
try
{
var gpo = new ComputerGroupPolicyObject();
using (RegistryKey rootRegistryKey = gpo.GetRootRegistryKey(section))
{
// Data can't be null so we can use this value to indicate key must be delete
if (settingValue == null)
{
using (RegistryKey subKey = rootRegistryKey.OpenSubKey(key, true))
{
if (subKey != null)
{
subKey.DeleteValue(valueName);
}
}
}
else
{
using (RegistryKey subKey = rootRegistryKey.CreateSubKey(key))
{
subKey.SetValue(valueName, settingValue, registryValueKind);
}
}
}
gpo.Save();
}
catch (Exception ex)
{
exception = ex;
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
if (exception != null)
throw exception;
}
public static object GetPolicySetting(string registryInformation)
{
string valueName;
GroupPolicySection section;
string key = Key(registryInformation, out valueName, out section);
// Thread must be STA
object result = null;
var t = new Thread(() =>
{
var gpo = new ComputerGroupPolicyObject();
using (RegistryKey rootRegistryKey = gpo.GetRootRegistryKey(section))
{
// Data can't be null so we can use this value to indicate key must be delete
using (RegistryKey subKey = rootRegistryKey.OpenSubKey(key, true))
{
if (subKey == null)
{
result = null;
}
else
{
result = subKey.GetValue(valueName);
}
}
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
return result;
}
private static string Key(string registryInformation, out string value, out GroupPolicySection section)
{
// Parse parameter of format HKCU\Software\Policies\Microsoft\Windows\Personalization!NoChangingSoundScheme
string[] split = registryInformation.Split('!');
string key = split[0];
string hive = key.Substring(0, key.IndexOf('\\'));
key = key.Substring(key.IndexOf('\\') + 1);
value = split[1];
if (hive.Equals(#"HKLM", StringComparison.OrdinalIgnoreCase)
|| hive.Equals(#"HKEY_LOCAL_MACHINE", StringComparison.OrdinalIgnoreCase))
{
section = GroupPolicySection.Machine;
}
else
{
section = GroupPolicySection.User;
}
return key;
}
/// <summary>
/// Retrieves the file system path to the root of the specified GPO section.
/// The path is in UNC format.
/// </summary>
public override string GetPathTo(GroupPolicySection section)
{
var sb = new StringBuilder(MaxLength);
var result = Instance.GetFileSysPath((uint)section, sb, MaxLength);
if (result != 0)
{
throw new Exception(string.Format("Unable to retrieve path to section '{0}'", Enum.GetName(typeof(GroupPolicySection), section)));
}
return sb.ToString();
}
}
And how to use it:
static void Main(string[] args)
{
ComputerGroupPolicyObject.SetPolicySetting(#"HKLM\Software\Policies\Microsoft\Windows\HomeGroup!DisableHomeGroup", "0", RegistryValueKind.DWord);
ComputerGroupPolicyObject.SetPolicySetting(#"HKLM\Software\Policies\Microsoft\Windows\HomeGroup!DisableHomeGroup", "1", RegistryValueKind.DWord);
ComputerGroupPolicyObject.SetPolicySetting(#"HKLM\Software\Policies\Microsoft\Windows\HomeGroup!DisableHomeGroup", null, RegistryValueKind.Unknown);
}
Code inspired from https://bitbucket.org/MartinEden/local-policy
Related
In Word/Excel you have to possibility to add Custom properties. (See Image)
Custom Properties.
As you guys can see there is the field: "Properties:", you can add any information you want there.
When you save the file and you go to the file location in the folder, you can right click -> Properties and you have all the tabs: General/Security/Details/Previous Versions. with the feature you add the tab Custom.
Now I want to get this information through coding: Custom Properties information. and extract it later to notepad.
So far i used the Shell32 but then I only get the information that is in the Details tab. I did some research and saw some possibilities with DSOfile.dll. But I want to know if there is a possibility to do this without installing other DLL?
This is my code so far with the Shell32.
static void Main(string[] args)
{
//using (StreamWriter writer = new StreamWriter(#"filepathhere"))
//{
//Console.SetOut(writer);
ReadProperties();
//}
}
static void ReadProperties()
{
List<string> arrHeaders = new List<string>();
Shell shell = new Shell();
Folder objFolder = shell.NameSpace(#"filepathhere");
FolderItem objFolderItem = objFolder.ParseName("filehere.doc");
for (int i = 0; i < short.MaxValue; i++)
{
string header = objFolder.GetDetailsOf(objFolder, i);
if (String.IsNullOrEmpty(header))
break;
arrHeaders.Add(header);
}
for ( int i = 0; i < arrHeaders.Count; i++)
{
Console.WriteLine("{0}\t{1}: {2}", i, arrHeaders[i], objFolder.GetDetailsOf(objFolderItem, i));
}
Console.ReadKey();
}
Thanks in advance!
Desu
Historically these properties were defined by the technology called "Structured Storage". The first Structured Storage implementation is the ancient (but still very alive) Compound File Format
After that, Microsoft added Structured Storage capabilities directly into NTFS. This allows you to define properties like author or title on any files (even .txt) files. Although the Explorer UI does not let you do this anymore for some reason, I think it still works programmatically.
And then, with Vista, Microsoft rebooted all that and introduced a superset of all this: the Windows Property System.
Unfortunately, there is no .NET API in the framework for all this. But Microsoft created an open source .NET library called the Windows API CodePack. So, the easiest way for you to extract properties is to add a reference to the WindowsAPICodePack Core NugetPackage and you can use it like this:
static void Main(string[] args)
{
foreach (var prop in new ShellPropertyCollection(#"mypath\myfile"))
{
Console.WriteLine(prop.CanonicalName + "=" + prop.ValueAsObject);
}
}
If you don't want to add extra DLLs, then you can extract the ShellPropertyCollection code from the WindowsAPICodePack source (Windows API Code Pack: Where is it?). It's quite a work but doable.
Another solution in your case, is to use the old Structure Storage native API. I've provided a sample that does this. Here is how you can use it:
static void Main(string[] args)
{
foreach (var prop in new StructuredStorage(#"mypath\myfile").Properties)
{
Console.WriteLine(prop.Name + "=" + prop.Value);
}
}
public sealed class StructuredStorage
{
public static readonly Guid SummaryInformationFormatId = new Guid("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}");
public static readonly Guid DocSummaryInformationFormatId = new Guid("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}");
public static readonly Guid UserDefinedPropertiesId = new Guid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");
private List<StructuredProperty> _properties = new List<StructuredProperty>();
public StructuredStorage(string filePath)
{
if (filePath == null)
throw new ArgumentNullException("filePath");
FilePath = filePath;
IPropertySetStorage propertySetStorage;
int hr = StgOpenStorageEx(FilePath, STGM.STGM_READ | STGM.STGM_SHARE_DENY_NONE | STGM.STGM_DIRECT_SWMR, STGFMT.STGFMT_ANY, 0, IntPtr.Zero, IntPtr.Zero, typeof(IPropertySetStorage).GUID, out propertySetStorage);
if (hr == STG_E_FILENOTFOUND || hr == STG_E_PATHNOTFOUND)
throw new FileNotFoundException(null, FilePath);
if (hr != 0)
throw new Win32Exception(hr);
try
{
LoadPropertySet(propertySetStorage, SummaryInformationFormatId);
LoadPropertySet(propertySetStorage, DocSummaryInformationFormatId);
}
finally
{
Marshal.ReleaseComObject(propertySetStorage);
}
// for some reason we can't read this one on the same COM ref?
LoadProperties(UserDefinedPropertiesId);
}
public string FilePath { get; private set; }
public IReadOnlyList<StructuredProperty> Properties
{
get
{
return _properties;
}
}
private void LoadPropertySet(IPropertySetStorage propertySetStorage, Guid fmtid)
{
IPropertyStorage propertyStorage;
int hr = propertySetStorage.Open(fmtid, STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE, out propertyStorage);
if (hr == STG_E_FILENOTFOUND || hr == STG_E_ACCESSDENIED)
return;
if (hr != 0)
throw new Win32Exception(hr);
IEnumSTATPROPSTG es;
propertyStorage.Enum(out es);
if (es == null)
return;
try
{
var stg = new STATPROPSTG();
int fetched;
do
{
hr = es.Next(1, ref stg, out fetched);
if (hr != 0 && hr != 1)
throw new Win32Exception(hr);
if (fetched == 1)
{
string name = GetPropertyName(fmtid, propertyStorage, stg);
var propsec = new PROPSPEC[1];
propsec[0] = new PROPSPEC();
propsec[0].ulKind = stg.lpwstrName != null ? PRSPEC.PRSPEC_LPWSTR : PRSPEC.PRSPEC_PROPID;
IntPtr lpwstr = IntPtr.Zero;
if (stg.lpwstrName != null)
{
lpwstr = Marshal.StringToCoTaskMemUni(stg.lpwstrName);
propsec[0].union.lpwstr = lpwstr;
}
else
{
propsec[0].union.propid = stg.propid;
}
var vars = new PROPVARIANT[1];
vars[0] = new PROPVARIANT();
try
{
hr = propertyStorage.ReadMultiple(1, propsec, vars);
if (hr != 0)
throw new Win32Exception(hr);
}
finally
{
if (lpwstr != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(lpwstr);
}
}
object value;
try
{
switch (vars[0].vt)
{
case VARTYPE.VT_BOOL:
value = vars[0].union.boolVal != 0 ? true : false;
break;
case VARTYPE.VT_BSTR:
value = Marshal.PtrToStringUni(vars[0].union.bstrVal);
break;
case VARTYPE.VT_CY:
value = decimal.FromOACurrency(vars[0].union.cyVal);
break;
case VARTYPE.VT_DATE:
value = DateTime.FromOADate(vars[0].union.date);
break;
case VARTYPE.VT_DECIMAL:
IntPtr dec = IntPtr.Zero;
Marshal.StructureToPtr(vars[0], dec, false);
value = Marshal.PtrToStructure(dec, typeof(decimal));
break;
case VARTYPE.VT_DISPATCH:
value = Marshal.GetObjectForIUnknown(vars[0].union.pdispVal);
break;
case VARTYPE.VT_ERROR:
case VARTYPE.VT_HRESULT:
value = vars[0].union.scode;
break;
case VARTYPE.VT_FILETIME:
value = DateTime.FromFileTime(vars[0].union.filetime);
break;
case VARTYPE.VT_I1:
value = vars[0].union.cVal;
break;
case VARTYPE.VT_I2:
value = vars[0].union.iVal;
break;
case VARTYPE.VT_I4:
value = vars[0].union.lVal;
break;
case VARTYPE.VT_I8:
value = vars[0].union.hVal;
break;
case VARTYPE.VT_INT:
value = vars[0].union.intVal;
break;
case VARTYPE.VT_LPSTR:
value = Marshal.PtrToStringAnsi(vars[0].union.pszVal);
break;
case VARTYPE.VT_LPWSTR:
value = Marshal.PtrToStringUni(vars[0].union.pwszVal);
break;
case VARTYPE.VT_R4:
value = vars[0].union.fltVal;
break;
case VARTYPE.VT_R8:
value = vars[0].union.dblVal;
break;
case VARTYPE.VT_UI1:
value = vars[0].union.bVal;
break;
case VARTYPE.VT_UI2:
value = vars[0].union.uiVal;
break;
case VARTYPE.VT_UI4:
value = vars[0].union.ulVal;
break;
case VARTYPE.VT_UI8:
value = vars[0].union.uhVal;
break;
case VARTYPE.VT_UINT:
value = vars[0].union.uintVal;
break;
case VARTYPE.VT_UNKNOWN:
value = Marshal.GetObjectForIUnknown(vars[0].union.punkVal);
break;
default:
value = null;
break;
}
}
finally
{
PropVariantClear(ref vars[0]);
}
var property = new StructuredProperty(fmtid, name, stg.propid);
property.Value = value;
_properties.Add(property);
}
}
while (fetched == 1);
}
finally
{
Marshal.ReleaseComObject(es);
}
}
private static string GetPropertyName(Guid fmtid, IPropertyStorage propertyStorage, STATPROPSTG stg)
{
if (!string.IsNullOrEmpty(stg.lpwstrName))
return stg.lpwstrName;
var propids = new int[1];
propids[0] = stg.propid;
var names = new string[1];
names[0] = null;
int hr = propertyStorage.ReadPropertyNames(1, propids, names);
if (hr == 0)
return names[0];
return null;
}
public void LoadProperties(Guid formatId)
{
IPropertySetStorage propertySetStorage;
int hr = StgOpenStorageEx(FilePath, STGM.STGM_READ | STGM.STGM_SHARE_DENY_NONE | STGM.STGM_DIRECT_SWMR, STGFMT.STGFMT_ANY, 0, IntPtr.Zero, IntPtr.Zero, typeof(IPropertySetStorage).GUID, out propertySetStorage);
if (hr == STG_E_FILENOTFOUND || hr == STG_E_PATHNOTFOUND)
throw new FileNotFoundException(null, FilePath);
if (hr != 0)
throw new Win32Exception(hr);
try
{
LoadPropertySet(propertySetStorage, formatId);
}
finally
{
Marshal.ReleaseComObject(propertySetStorage);
}
}
private const int STG_E_FILENOTFOUND = unchecked((int)0x80030002);
private const int STG_E_PATHNOTFOUND = unchecked((int)0x80030003);
private const int STG_E_ACCESSDENIED = unchecked((int)0x80030005);
private enum PRSPEC
{
PRSPEC_LPWSTR = 0,
PRSPEC_PROPID = 1
}
private enum STGFMT
{
STGFMT_ANY = 4,
}
[Flags]
private enum STGM
{
STGM_READ = 0x00000000,
STGM_READWRITE = 0x00000002,
STGM_SHARE_DENY_NONE = 0x00000040,
STGM_SHARE_DENY_WRITE = 0x00000020,
STGM_SHARE_EXCLUSIVE = 0x00000010,
STGM_DIRECT_SWMR = 0x00400000
}
// we only define what we handle
private enum VARTYPE : short
{
VT_I2 = 2,
VT_I4 = 3,
VT_R4 = 4,
VT_R8 = 5,
VT_CY = 6,
VT_DATE = 7,
VT_BSTR = 8,
VT_DISPATCH = 9,
VT_ERROR = 10,
VT_BOOL = 11,
VT_UNKNOWN = 13,
VT_DECIMAL = 14,
VT_I1 = 16,
VT_UI1 = 17,
VT_UI2 = 18,
VT_UI4 = 19,
VT_I8 = 20,
VT_UI8 = 21,
VT_INT = 22,
VT_UINT = 23,
VT_HRESULT = 25,
VT_LPSTR = 30,
VT_LPWSTR = 31,
VT_FILETIME = 64,
}
[StructLayout(LayoutKind.Explicit)]
private struct PROPVARIANTunion
{
[FieldOffset(0)]
public sbyte cVal;
[FieldOffset(0)]
public byte bVal;
[FieldOffset(0)]
public short iVal;
[FieldOffset(0)]
public ushort uiVal;
[FieldOffset(0)]
public int lVal;
[FieldOffset(0)]
public uint ulVal;
[FieldOffset(0)]
public int intVal;
[FieldOffset(0)]
public uint uintVal;
[FieldOffset(0)]
public long hVal;
[FieldOffset(0)]
public ulong uhVal;
[FieldOffset(0)]
public float fltVal;
[FieldOffset(0)]
public double dblVal;
[FieldOffset(0)]
public short boolVal;
[FieldOffset(0)]
public int scode;
[FieldOffset(0)]
public long cyVal;
[FieldOffset(0)]
public double date;
[FieldOffset(0)]
public long filetime;
[FieldOffset(0)]
public IntPtr bstrVal;
[FieldOffset(0)]
public IntPtr pszVal;
[FieldOffset(0)]
public IntPtr pwszVal;
[FieldOffset(0)]
public IntPtr punkVal;
[FieldOffset(0)]
public IntPtr pdispVal;
}
[StructLayout(LayoutKind.Sequential)]
private struct PROPSPEC
{
public PRSPEC ulKind;
public PROPSPECunion union;
}
[StructLayout(LayoutKind.Explicit)]
private struct PROPSPECunion
{
[FieldOffset(0)]
public int propid;
[FieldOffset(0)]
public IntPtr lpwstr;
}
[StructLayout(LayoutKind.Sequential)]
private struct PROPVARIANT
{
public VARTYPE vt;
public ushort wReserved1;
public ushort wReserved2;
public ushort wReserved3;
public PROPVARIANTunion union;
}
[StructLayout(LayoutKind.Sequential)]
private struct STATPROPSTG
{
[MarshalAs(UnmanagedType.LPWStr)]
public string lpwstrName;
public int propid;
public VARTYPE vt;
}
[StructLayout(LayoutKind.Sequential)]
private struct STATPROPSETSTG
{
public Guid fmtid;
public Guid clsid;
public uint grfFlags;
public System.Runtime.InteropServices.ComTypes.FILETIME mtime;
public System.Runtime.InteropServices.ComTypes.FILETIME ctime;
public System.Runtime.InteropServices.ComTypes.FILETIME atime;
public uint dwOSVersion;
}
[DllImport("ole32.dll")]
private static extern int StgOpenStorageEx([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, STGM grfMode, STGFMT stgfmt, int grfAttrs, IntPtr pStgOptions, IntPtr reserved2, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IPropertySetStorage ppObjectOpen);
[DllImport("ole32.dll")]
private static extern int PropVariantClear(ref PROPVARIANT pvar);
[Guid("0000013B-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IEnumSTATPROPSETSTG
{
[PreserveSig]
int Next(int celt, ref STATPROPSETSTG rgelt, out int pceltFetched);
// rest ommited
}
[Guid("00000139-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IEnumSTATPROPSTG
{
[PreserveSig]
int Next(int celt, ref STATPROPSTG rgelt, out int pceltFetched);
// rest ommited
}
[Guid("00000138-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IPropertyStorage
{
[PreserveSig]
int ReadMultiple(uint cpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPVARIANT[] rgpropvar);
[PreserveSig]
int WriteMultiple(uint cpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPVARIANT[] rgpropvar, uint propidNameFirst);
[PreserveSig]
int DeleteMultiple(uint cpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec);
[PreserveSig]
int ReadPropertyNames(uint cpropid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] rgpropid, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 0)] string[] rglpwstrName);
[PreserveSig]
int NotDeclared1();
[PreserveSig]
int NotDeclared2();
[PreserveSig]
int Commit(uint grfCommitFlags);
[PreserveSig]
int NotDeclared3();
[PreserveSig]
int Enum(out IEnumSTATPROPSTG ppenum);
// rest ommited
}
[Guid("0000013A-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IPropertySetStorage
{
[PreserveSig]
int Create([MarshalAs(UnmanagedType.LPStruct)] Guid rfmtid, [MarshalAs(UnmanagedType.LPStruct)] Guid pclsid, uint grfFlags, STGM grfMode, out IPropertyStorage ppprstg);
[PreserveSig]
int Open([MarshalAs(UnmanagedType.LPStruct)] Guid rfmtid, STGM grfMode, out IPropertyStorage ppprstg);
[PreserveSig]
int NotDeclared3();
[PreserveSig]
int Enum(out IEnumSTATPROPSETSTG ppenum);
}
}
public sealed class StructuredProperty
{
public StructuredProperty(Guid formatId, string name, int id)
{
FormatId = formatId;
Name = name;
Id = id;
}
public Guid FormatId { get; private set; }
public string Name { get; private set; }
public int Id { get; private set; }
public object Value { get; set; }
public override string ToString()
{
return Name;
}
}
You can try NPOI engine to extract properties from different Office files (doc, xls, xlsx, docx, etc). This component doesn't have any third party dependencies and you don't need Office to use it.
However, this library is a bit tricky because you need to use different types of property extractors for different type of files. Good code sample can be found in official Git Hub repository TestHPSFPropertiesExtractor.
NuGet package can be found here.
There's a set of NuGet packages called NetOffice that you can use. There are packages for each of the Office applications, plus a few core assemblies. Get NetOffice.Word and NetOffice.Excel and install them in your solution. There's a little documentation at the Codeplex site, but I had to browse the source to really understand what was going on. Here's a sample program:
using NetOffice.OfficeApi;
using System;
namespace Office_Doc_Reader
{
class Program
{
static void Main(string[] args)
{
using (var wordApp = new NetOffice.WordApi.Application())
using (var excelApp = new NetOffice.ExcelApi.Application())
{
var doc = wordApp.Documents.Open("C:\\Users\\John\\Desktop\\test.docx");
var xls = excelApp.Workbooks.Open("C:\\Users\\John\\Desktop\\test.xlsx");
var customProperties = (DocumentProperties)doc.CustomDocumentProperties;
foreach (var property in customProperties)
{
Console.WriteLine(String.Format("Name: {0}, Value: {1}, Type: {2}", property.Name, property.Value, property.Type));
}
customProperties = (DocumentProperties)xls.CustomDocumentProperties;
foreach (var property in customProperties)
{
Console.WriteLine(String.Format("Name: {0}, Value: {1}, Type: {2}", property.Name, property.Value, property.Type));
}
}
Console.ReadKey();
}
}
}
That shows the following results:
Name: Custom prop 1, Value: Text Value, Type: msoPropertyTypeString
Name: Custom prop 2, Value: 2/21/2016 12:00:00 AM, Type: msoPropertyTypeDate
Name: Custom prop 3, Value: 42, Type: msoPropertyTypeNumber
Name: Custom prop 4, Value: True, Type: msoPropertyTypeBoolean
Name: Foo, Value: abc, Type: msoPropertyTypeString
Name: Bar, Value: 1/1/1970 12:00:00 AM, Type: msoPropertyTypeDate
Name: Baz, Value: 3.14159, Type: msoPropertyTypeFloat
Name: Qux, Value: False, Type: msoPropertyTypeBoolean
For a Word and Excel file with these properties:
I've not worked with these much at all, so I won't be able to go much deeper than this. Hope it helps.
You may use OpenXml SDK from Microsoft. I believe it is able to get any info from word/excel files.
Have a look at this https://msdn.microsoft.com/en-us/library/office/hh674468.aspx also this https://msdn.microsoft.com/en-us/library/office/bb448854.aspx
or
http://openxmldeveloper.org/
There could be a more generic approach.
If your source is a ...x file, the document can be extracted via XML queries.
If you unzip the file (eg.g with 7-Zip) you will find a file called custom.xml in the subfolder docProps.
The properties can easily be found within the XML file
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2" name="SAPDOKNR">
<vt:lpwstr>10002210058</vt:lpwstr>
</property>
...
I'm trying to find Unicast, Dns and Gateway Address in windows IOT.
Normally I can access these values with NetworkInterface.GetAllNetworkInterfaces() method.
But in UWP, that method is missing.
Is there any alternative for getting these values?
You could try to PInvoke methods from Iphlpapi.dll. There are several methods that may contain the Unicast, Dns and Gateway info you're looking for, like GetInterfaceInfo(), GetAdaptersInfo(), GetAdaptersAdresses(), etc. Please see a complete list of available methods here: IP Helper Functions - MSDN. Eventually more than one method might be necessary.
As an example on how to do it, here's some sample code from PInvoke.Net retrieving interface names in my local computer, implemented as a standard UWP app:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
List<string> list = new List<string>();
IP_INTERFACE_INFO ips = Iphlpapi.GetInterfaceInfo();
list.Add(string.Format("Adapter count = {0}", ips.NumAdapters));
foreach (IP_ADAPTER_INDEX_MAP ip in ips.Adapter)
list.Add(string.Format("Index = {0}, Name = {1}", ip.Index, ip.Name));
listView1.ItemsSource = list;
}
}
// PInvoke
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct IP_ADAPTER_INDEX_MAP
{
public int Index;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = PInvokes.MAX_ADAPTER_NAME)]
public String Name;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct IP_INTERFACE_INFO
{
public int NumAdapters;
public IP_ADAPTER_INDEX_MAP[] Adapter;
public static IP_INTERFACE_INFO FromByteArray(Byte[] buffer)
{
unsafe
{
IP_INTERFACE_INFO rv = new IP_INTERFACE_INFO();
int iNumAdapters = 0;
Marshal.Copy(buffer, 0, new IntPtr(&iNumAdapters), 4);
IP_ADAPTER_INDEX_MAP[] adapters = new IP_ADAPTER_INDEX_MAP[iNumAdapters];
rv.NumAdapters = iNumAdapters;
rv.Adapter = new IP_ADAPTER_INDEX_MAP[iNumAdapters];
int offset = sizeof(int);
for (int i = 0; i < iNumAdapters; i++)
{
IP_ADAPTER_INDEX_MAP map = new IP_ADAPTER_INDEX_MAP();
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(map));
Marshal.StructureToPtr(map, ptr, false);
Marshal.Copy(buffer, offset, ptr, Marshal.SizeOf(map));
//map = (IP_ADAPTER_INDEX_MAP)Marshal.PtrToStructure(ptr, typeof(IP_ADAPTER_INDEX_MAP));
map = Marshal.PtrToStructure<IP_ADAPTER_INDEX_MAP>(ptr);
Marshal.FreeHGlobal(ptr);
rv.Adapter[i] = map;
offset += Marshal.SizeOf(map);
}
return rv;
}
}
}
internal class PInvokes
{
public const int MAX_ADAPTER_NAME = 128;
public const int ERROR_INSUFFICIENT_BUFFER = 122;
public const int ERROR_SUCCESS = 0;
[DllImport("Iphlpapi.dll", CharSet = CharSet.Unicode)]
public static extern int GetInterfaceInfo(Byte[] PIfTableBuffer, ref int size);
[DllImport("Iphlpapi.dll", CharSet = CharSet.Unicode)]
public static extern int IpReleaseAddress(ref IP_ADAPTER_INDEX_MAP AdapterInfo);
}
public class Iphlpapi
{
public static IP_INTERFACE_INFO GetInterfaceInfo()
{
int size = 0;
int r = PInvokes.GetInterfaceInfo(null, ref size);
Byte[] buffer = new Byte[size];
r = PInvokes.GetInterfaceInfo(buffer, ref size);
if (r != PInvokes.ERROR_SUCCESS)
throw new Exception("GetInterfaceInfo returned an error.");
IP_INTERFACE_INFO info = IP_INTERFACE_INFO.FromByteArray(buffer);
return info;
}
}
Try this code Snippet I found here:
https://social.msdn.microsoft.com/Forums/en-US/27a8b7a8-8071-4bc1-bbd4-e7c1fc2bd8d7/windows-10-iot-core-how-do-you-create-a-tcp-server-and-client?forum=WindowsIoT
public static string GetDirectConnectionName()
{
var icp = NetworkInformation.GetInternetConnectionProfile();
if (icp != null)
{
if(icp.NetworkAdapter.IanaInterfaceType == EthernetIanaType)
{
return icp.ProfileName;
}
}
return null;
}
public static string GetCurrentNetworkName()
{
var icp = NetworkInformation.GetInternetConnectionProfile();
if (icp != null)
{
return icp.ProfileName;
}
var resourceLoader = ResourceLoader.GetForCurrentView();
var msg = resourceLoader.GetString("NoInternetConnection");
return msg;
}
public static string GetCurrentIpv4Address()
{
var icp = NetworkInformation.GetInternetConnectionProfile();
if (icp != null && icp.NetworkAdapter != null && icp.NetworkAdapter.NetworkAdapterId != null)
{
var name = icp.ProfileName;
var hostnames = NetworkInformation.GetHostNames();
foreach (var hn in hostnames)
{
if (hn.IPInformation != null &&
hn.IPInformation.NetworkAdapter != null &&
hn.IPInformation.NetworkAdapter.NetworkAdapterId != null &&
hn.IPInformation.NetworkAdapter.NetworkAdapterId == icp.NetworkAdapter.NetworkAdapterId &&
hn.Type == HostNameType.Ipv4)
{
return hn.CanonicalName;
}
}
}
var resourceLoader = ResourceLoader.GetForCurrentView();
var msg = resourceLoader.GetString("NoInternetConnection");
return msg;
}
As jstreet commented, Invoke is the solution. I tried with a Lumia 950, and GetAdaptersInfo() works, not as IcmpSendEcho().
With the following link you should do it:
http://www.pinvoke.net/default.aspx/iphlpapi/GetAdaptersInfo.html
I have an application that is meant to mirror files from one location to another. In one segment of this program ( likely the most important ) the application opens impersonation contexts for both the source and destination; assuming that credentials have been provided. Once these contexts have been opened, the program executes the actual mirroring of files from one location to another, and then closes the aforementioned contexts.
It looks something like this:
protected virtual void MirrorChanges()
{
if (this.Source == null)
throw new InvalidOperationException();
else if (!this.Source.Exists)
throw new InvalidOperationException();
else
{
if( this.SourceImpersonator != null )
if(!this.SourceImpersonator.Open())
{
throw new Exception("FolderMirror cannot impersonate Source user. Please review the associated credentials.");
}
if( this.DestinationImpersonator != null )
if(!this.DestinationImpersonator.Open())
{
throw new Exception("FolderMirror cannot impersonate Destination user. Please review the associated credentials.");
}
this.MirrorChanges(this.Source);
if( this.DestinationImpersonator != null )
this.DestinationImpersonator.Close();
if( this.SourceImpersonator != null )
this.SourceImpersonator.Close();
return;
}
}
Now; the question you're all begging - what's in the 'Open' and 'Close' methods of these supposed 'impersonators'? Much of this was taken from some other examples found about the internet, but here we go:
public class UserImpersonator
{
public Boolean Open()
{
// Actively researching why the 'DuplicateToken' method is necessary in this method - like
// I said earlier, much of this is sourced from examples. I did some research and do note that
// there is a 'SECURITY_IMPERSONATION_LEVEL' variable in this method; but that strikes me as
// rather perplexing if this method's action is to simply 'duplicate a token' - but I'm off to
//the manual for reviewing that information.
if (!LogonUser(this.Username, this.Domain, this.Password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, ref this.PrimaryToken))
{
RaiseLastError();
return false;
}
else if (!DuplicateToken(this.PrimaryToken, 2, ref this.MutatedToken))
{
RaiseLastError();
return false;
}
else
{
try
{
this._TargetIdentity = new WindowsIdentity(this.MutatedToken);
this._ImpersonationContext = this._TargetIdentity.Impersonate();
return true;
}
catch (Exception e)
{
return false;
}
}
}
public void Close()
{
if( this._ImpersonationContext != null )
this._ImpersonationContext.Undo();
if( this.PrimaryToken != null )
if (!CloseHandle(this.PrimaryToken))
RaiseLastError();
}
// With some of this action, actually toward the top of the file...
DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private unsafe static extern int FormatMessage(int dwFlags, ref IntPtr lpSource, int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize, IntPtr* arguments);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr existingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr duplicateTokenHandle);
}
Now - there are clearly some things I could tighten up, but to get to the root of the issue here - In a situation where I provide a known valid username, password, and domain - I am denied access to actually replace the file in the destination.
[Edit] I've now ( as any sane programmer would )( edits applied above ) wrapped conditionals around the 'Impersonator.Open' clauses to ensure that they sort out - with true evaluations. After stepping through execution of the 'Open' method I'm coming up with successes all the way through.
[Edit] It's probably valuable to mention that I've taken these open and close methods and placed them in an 'Execute' method that takes a Delegate as a parameter. At the time it seemed more appropriate than the current implementation; but after writing an extra thousand lines or so and still getting the same result ( most of which was for actually negotiating the files while int he context of the execute method ); I gave up and haven't come back to it. Here's that tidbit, in-case someone is interested.
public class UserImpersonator()
{
public Object Execute(System.Delegate Method)
{
if (Method == null)
throw new InvalidOperationException("Impersonator fixed-method already provided. Cannot implement another method on this impersonator." );
else if (!this.Open())
return null;
else
{
try
{
this._Executing = true;
Object ReturnValue = Method.DynamicInvoke();
this.Close();
this._Executing = false;
return ReturnValue;
}
catch (Exception e)
{
return null;
}
}
}
}
[Add] I should also mention that on my local system ( have yet to test in the deployment [server] environment ), if I provide totally invalid credentials, I still get access to both read and write. I presume that this means that I retain credentials that have already been opened - but if that's the case my [uneducated] assumption that 'stacking impersonation won't work' really falls apart.
I've taken quite a few passes at this to no avail; so if anyone has any suggestions or questions I am all ears.
Sometimes trial and error prevails.
The adjustment that is required to correct this issue is a modification of the LogonType, and LogonProvider variables in the LogonUser method. In this particular instance, the valid ( seemingly only working ) uses are with the LOGON32_PROVIDER_DEFAULT and LOGON32_LOGON_INTERACTIVE constants.
I personally do not know why[, but would be very interested in some greater detail than that found here].
After some general trial and error, for my application, the corrected code follows. I hope that this can serve as an [early revision of an] authoritative reference for the community; as most of the implementations are ... less than thorough.
Before the code dump, it would be remiss of me to not note the potential implementations of this code.
1. Create a new UserImpersonator using the UserImpersonator(String Username,String Password,String Domain,System.Delegate Method) constructor to define the credentials, and the method to be invoked; and then 'Execute' the UserImpersonator using either of the overloaded Execute methods that do not require a delegate. By nature, these methods refer directly to the method that was stored at construction, or set at a later time.
2. Create a new UserImpersonator using the UserImpersonator(String Username, String Password, String Domain) constructor, and perform one of a few actions:
1. Set the UserImpersonator's Method and Execute it at a later time.
2. Run an Execute overload that requires a delegate parameter on the UserImpersonator, and provide a delegate method for the impersonator to execute.
3. Execute the 'UserImpersonator.Open' method to open the user context, execute your user-specific code, and then execute the 'UserImpersonator.Close' method to finalize the operation.
Here we go though:
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Security.Principal;
using System.Linq;
using System.Text;
namespace TopSekrit.Credentials
{
public class UserImpersonator : IDisposable
{
#region Delegates
// Port from generic event handler
public delegate void SimpleEventDelegate(SimpleEventArgument Argument);
#endregion
#region Supporting Classes
// Port from generic event handler
public class SimpleEventArgument
{
public Object Source = null;
public Object Message = null;
public SimpleEventArgument(Object Source, String Message)
{
this.Source = Source;
this.Message = Message;
}
}
#endregion
#region Imports
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private unsafe static extern int FormatMessage(int dwFlags, ref IntPtr lpSource, int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize, IntPtr* arguments);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr existingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr duplicateTokenHandle);
#endregion
#region Constants
// Logon Types as defined in Winbase.h
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_BATCH = 4;
const int LOGON32_LOGON_SERVICE = 5;
const int LOGON32_LOGON_UNKNOWN = 6;
const int LOGON32_LOGON_UNLOCK = 7;
const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
// Logon Providers as defined in Winbase.h
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_PROVIDER_WINNT35 = 1;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT50 = 3;
#endregion
#region Events
public event SimpleEventDelegate OnImpersonationReset = null;
public event SimpleEventDelegate OnImpersonationOpened = null;
public event SimpleEventDelegate OnImpersonationClosed = null;
public event SimpleEventDelegate OnImpersonatedExecutionStarted = null;
public event SimpleEventDelegate OnImpersonatedExecutionFinished = null;
#endregion
#region Properties
protected String _Username = String.Empty;
public String Username
{
get
{
return this._Username;
}
set
{
if (this.IsExecuting)
throw new InvalidOperationException("Cannot set Username on UserImpersonator while impersonation is executing.");
else if (this.IsOpen)
throw new InvalidOperationException("Cannot set Username on UserImpersonator while impersonation context is open.");
else
{
this._Username = value;
this.ResetImpersonation();
}
}
}
protected String _Password = String.Empty;
public String Password
{
get
{
return this._Password;
}
set
{
if (this.IsExecuting)
throw new InvalidOperationException("Cannot set Password on UserImpersonator while impersonation is executing.");
else if (this.IsOpen)
throw new InvalidOperationException("Cannot set Password on UserImpersonator while impersonation context is open.");
else
{
this._Password = value;
this.ResetImpersonation();
}
}
}
protected String _Domain = String.Empty;
public String Domain
{
get
{
return this._Domain;
}
set
{
if (this.IsExecuting)
throw new InvalidOperationException("Cannot set Domain on UserImpersonator while impersonation is executing.");
else if (this.IsOpen)
throw new InvalidOperationException("Cannot set Domain on UserImpersonator while impersonation context is open.");
else
{
this._Domain = value;
this.ResetImpersonation();
}
}
}
protected System.Delegate _Method = null;
public System.Delegate Method
{
get
{
return this._Method;
}
set
{
this._Method = value;
}
}
protected IntPtr PrimaryToken = IntPtr.Zero;
protected IntPtr MutatedToken = IntPtr.Zero;
protected WindowsIdentity _TargetIdentity = null;
public WindowsIdentity TargetIdentity
{
get
{
return this._TargetIdentity;
}
}
protected WindowsImpersonationContext _ImpersonationContext = null;
public WindowsImpersonationContext ImpersonationContext
{
get
{
return this._ImpersonationContext;
}
}
protected Boolean _IsExecuting = false;
public Boolean IsExecuting
{
get
{
return this._IsExecuting;
}
}
public Boolean IsOpen
{
get
{
if (this.PrimaryToken != null)
return true;
else if (this.MutatedToken != null)
return true;
else if (this.TargetIdentity != null)
return true;
else if (this.ImpersonationContext != null)
return true;
else
return false;
}
}
protected int _LogonType = LOGON32_LOGON_INTERACTIVE;
public int LogonType
{
get
{
return this._LogonType;
}
set
{
if (this.IsExecuting)
throw new InvalidOperationException("Cannot set LogonType on UserImpersonator while impersonation is executing.");
else if (this.IsOpen)
throw new InvalidOperationException("Cannot set LogonType on UserImpersonator while impersonation context is open.");
else
{
this._LogonType = value;
this.ResetImpersonation();
}
}
}
protected int _LogonProvider = LOGON32_PROVIDER_DEFAULT;
public int LogonProvider
{
get
{
return this._LogonProvider;
}
set
{
if (this.IsExecuting)
throw new InvalidOperationException("Cannot set LogonProvider on UserImpersonator while impersonation is executing.");
else if (this.IsOpen)
throw new InvalidOperationException("Cannot set LogonProvider on UserImpersonator while impersonation context is open.");
else
{
this._LogonProvider = value;
this.ResetImpersonation();
}
}
}
#endregion
#region Constructors
public UserImpersonator(String Username,String Password,String Domain,System.Delegate Method,int LogonType,int LogonProvider)
{
if (String.IsNullOrEmpty(Username))
throw new ArgumentNullException();
else
{
this._Username = Username;
this._Password = Password;
this._Domain = Domain;
this._Method = Method;
this._LogonType = LogonType;
this._LogonProvider = LogonProvider;
return;
}
}
public UserImpersonator(String Username, String Password, String Domain, System.Delegate Method, int LogonType)
: this(Username, Password, Domain, Method, LogonType, LOGON32_PROVIDER_DEFAULT)
{
}
public UserImpersonator(String Username, String Password, String Domain, System.Delegate Method)
: this(Username,Password,Domain,Method,LOGON32_LOGON_INTERACTIVE)
{
}
public UserImpersonator(String Username, String Password, String Domain)
:this( Username, Password, Domain, null)
{
}
public UserImpersonator(String Username, String Password)
: this(Username, Password,String.Empty)
{
}
public UserImpersonator(String Username)
: this(Username, String.Empty)
{
}
#endregion
#region Impersonated Execution
public virtual Object Execute()
{
if (this.IsExecuting)
throw new InvalidOperationException("UserImpersonator cannot Execute while another execution is already in progress.");
else if (this.Method == null)
throw new InvalidOperationException("UserImpersonator cannot Execute without a supplied, or stored Method to invoke.");
else if (!this.Open())
throw new InvalidOperationException("Could not open security context.");
else
{
try
{
this._IsExecuting = true;
Object ReturnValue = this.Method.DynamicInvoke();
this.Close();
this._IsExecuting = false;
return ReturnValue;
}
catch (Exception e)
{
return null;
}
}
}
public virtual Object Execute(params object[] Arguments)
{
if (this.IsExecuting)
throw new InvalidOperationException("UserImpersonator cannot Execute while another execution is already in progress.");
else if (this.Method == null)
throw new InvalidOperationException("UserImpersonator cannot Execute without a supplied, or stored Method to invoke.");
else if (!this.Open())
throw new InvalidOperationException("Could not open security context.");
else
{
try
{
this._IsExecuting = true;
Object ReturnValue = this.Method.DynamicInvoke(Arguments);
this.Close();
this._IsExecuting = false;
return ReturnValue;
}
catch (Exception e)
{
return null;
}
}
}
public virtual Object Execute(System.Delegate Method)
{
if (this.IsExecuting)
throw new InvalidOperationException("UserImpersonator cannot Execute while another execution is already in progress.");
else if (Method == null)
throw new InvalidOperationException("UserImpersonator cannot Execute without a supplied, or stored Method to invoke.");
else if (!this.Open())
throw new InvalidOperationException("Could not open security context.");
else
{
try
{
this._IsExecuting = true;
Object ReturnValue = Method.DynamicInvoke();
this.Close();
this._IsExecuting = false;
return ReturnValue;
}
catch (Exception e)
{
return null;
}
}
}
public virtual Object Execute(System.Delegate Method, params object[] Arguments)
{
if (this.IsExecuting)
throw new InvalidOperationException("UserImpersonator cannot Execute while another execution is already in progress.");
else if (Method == null)
throw new InvalidOperationException("UserImpersonator cannot Execute without a supplied, or stored Method to invoke.");
else if (!this.Open())
throw new InvalidOperationException("Could not open security context.");
else
{
try
{
this._IsExecuting = true;
Object ReturnValue = Method.DynamicInvoke(Arguments);
this.Close();
this._IsExecuting = false;
return ReturnValue;
}
catch (Exception e)
{
return null;
}
}
}
#endregion
#region Impersonation / Depersonation
public virtual Boolean Open()
{
if (this.IsOpen)
{
if( this.IsExecuting )
throw new InvalidOperationException("UserImpersonator cannot Open user context while a user context is already open and executing.");
else
{
this.Close();
return this.Open();
}
}
else if (!LogonUser(this.Username, this.Domain, this.Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref this.PrimaryToken))
throw this.GetLastException();
else if (!DuplicateToken(this.PrimaryToken, 2, ref this.MutatedToken))
throw this.GetLastException();
else
{
try
{
this._TargetIdentity = new WindowsIdentity(this.MutatedToken);
}
catch (Exception e)
{
throw new Exception("UserImpersonator could not Open user context. An exception was encountered while creating the WindowsIdentity.\r\n" + e.Message + "\r\n" + e.StackTrace);
}
finally
{
try
{
this._ImpersonationContext = this._TargetIdentity.Impersonate();
}
catch (Exception e)
{
throw new Exception("UserImpersonator could not Open user context. An exception was encountered while creating the WindowsImpersonationContext.\r\n" + e.Message + "\r\n" + e.StackTrace);
}
finally
{
this.FireImpersonationOpened();
}
}
return true;
}
}
public virtual void Close()
{
if (this.IsExecuting)
throw new InvalidOperationException("UserImpersonator cannot Close impersonation context while in execution.");
else
{
try
{
if (this._TargetIdentity != null)
{
this._TargetIdentity.Dispose();
this._TargetIdentity = null;
}
}
catch (Exception e)
{
throw new Exception("Exception encountered while disposing TargetIdentity on UserImpersonator.\r\n" + e.Message + "\r\n" + e.StackTrace);
}
finally
{
try
{
if (this._ImpersonationContext != null)
{
this._ImpersonationContext.Undo();
this._ImpersonationContext.Dispose();
this._ImpersonationContext = null;
}
}
catch (Exception e)
{
throw new Exception("Exception encountered while undoing or disposing ImpersonationContext on UserImpersonator.\r\n" + e.Message + "\r\n" + e.StackTrace);
}
finally
{
try
{
if (this.MutatedToken != null)
if (!CloseHandle(MutatedToken))
this.GetLastException();
}
catch (Exception e)
{
throw new Exception("Exception encountered while closing MutatedToken on UserImpersonator.\r\n" + e.Message + "\r\n" + e.StackTrace);
}
finally
{
try
{
if (this.PrimaryToken != null)
if (!CloseHandle(this.PrimaryToken))
this.GetLastException();
}
catch (Exception e)
{
throw new Exception("Exception encountered while closing PrimaryToken on UserImpersonator.\r\n" + e.Message + "\r\n" + e.StackTrace);
}
finally
{
this.FireImpersonationClosed();
}
}
}
}
return;
}
}
protected virtual void ResetImpersonation()
{
if (this.IsExecuting)
throw new InvalidOperationException("UserImpersonator cannot ResetImpersonation while impersonation is already executing.");
else if (this.IsOpen)
{
this.Close();
this.ResetImpersonation();
return;
}
else
{
this.Open();
this.FireImpersonationReset();
return;
}
}
#endregion
#region Error Handling
private Exception GetLastException()
{
return new ApplicationException(this.GetErrorMessage(Marshal.GetLastWin32Error()));
}
public unsafe string GetErrorMessage(int ErrorCode)
{
int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
int messageSize = 255;
string lpMsgBuf = "";
int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
IntPtr ptrlpSource = IntPtr.Zero;
IntPtr ptrArguments = IntPtr.Zero;
int retVal = FormatMessage(dwFlags, ref ptrlpSource, ErrorCode, 0, ref lpMsgBuf, messageSize, &ptrArguments);
if (retVal == 0)
return string.Format("Failed to format message for error code '{0}'.", ErrorCode);
return lpMsgBuf;
}
#endregion
#region Disposability
public virtual void Dispose()
{
this.Close();
this._Username = null;
this._Password = null;
this._Domain = null;
this._Method = null;
return;
}
#endregion
#region Event Firing
protected virtual void FireImpersonationReset()
{
if (this.OnImpersonationReset != null)
this.OnImpersonationReset(new Events.SimpleArgument(this, "Impersonation context has been reset."));
return;
}
protected virtual void FireImpersonationOpened()
{
if (this.OnImpersonationOpened != null)
this.OnImpersonationOpened(new Events.SimpleArgument(this, "Impersonation context has been opened."));
return;
}
protected virtual void FireImpersonationClosed()
{
if (this.OnImpersonationClosed != null)
this.OnImpersonationClosed(new Events.SimpleArgument(this, "Impersonation context has been closed."));
return;
}
protected virtual void FireImpersonationExecutionStarted()
{
if (this.OnImpersonatedExecutionStarted != null )
this.OnImpersonatedExecutionStarted(new Events.SimpleArgument(this, "Impersonated execution has started."));
return;
}
protected virtual void FireImpersonationExecutionFinished()
{
if (this.OnImpersonatedExecutionFinished != null)
this.OnImpersonatedExecutionFinished(new Events.SimpleArgument(this, "Impersonated execution has finished."));
return;
}
#endregion
}
}
[Edit]: Updated 8/12/14 - Added LogonType and LogonProvider constructors. Open method overrides to follow at my first availability.
My feeling is that this is one of the more thorough implementations of windows user impersonation - I hope you all find some use in it. Questions or comments are welcome; as I am sure this has room for improvement still.
When we open Package Manager Console in any open solution, it shows all the projects of that solution. How it is loading all the projects of the same solution.
When I tried with below shown code it is fetching me projects of the first solution which I have opened.
private List<Project> GetProjects()
{
var dte = (DTE)Marshal.GetActiveObject(string.Format(CultureInfo.InvariantCulture, "VisualStudio.DTE.{0}.0", targetVsVersion));
var projects = dte.Solution.OfType<Project>().ToList();
return projects;
}
Here are a various set of functions that allow you to enumerate projects in a given solution. This is how you would use it with the current solution:
// get current solution
IVsSolution solution = (IVsSolution)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(IVsSolution));
foreach(Project project in GetProjects(solution))
{
....
}
....
public static IEnumerable<EnvDTE.Project> GetProjects(IVsSolution solution)
{
foreach (IVsHierarchy hier in GetProjectsInSolution(solution))
{
EnvDTE.Project project = GetDTEProject(hier);
if (project != null)
yield return project;
}
}
public static IEnumerable<IVsHierarchy> GetProjectsInSolution(IVsSolution solution)
{
return GetProjectsInSolution(solution, __VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION);
}
public static IEnumerable<IVsHierarchy> GetProjectsInSolution(IVsSolution solution, __VSENUMPROJFLAGS flags)
{
if (solution == null)
yield break;
IEnumHierarchies enumHierarchies;
Guid guid = Guid.Empty;
solution.GetProjectEnum((uint)flags, ref guid, out enumHierarchies);
if (enumHierarchies == null)
yield break;
IVsHierarchy[] hierarchy = new IVsHierarchy[1];
uint fetched;
while (enumHierarchies.Next(1, hierarchy, out fetched) == VSConstants.S_OK && fetched == 1)
{
if (hierarchy.Length > 0 && hierarchy[0] != null)
yield return hierarchy[0];
}
}
public static EnvDTE.Project GetDTEProject(IVsHierarchy hierarchy)
{
if (hierarchy == null)
throw new ArgumentNullException("hierarchy");
object obj;
hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out obj);
return obj as EnvDTE.Project;
}
There may be a nicer way but I had a quick go at this and found this to work (it assumes you have a way of knowing the solution name). According to this post, GetActiveObject does not guarantee the current instance of VS which is why you're getting results from another instance. Instead, you can use the GetDTE method shown there:
[DllImport("ole32.dll")]
private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);
public static DTE GetDTE(int processId)
{
string progId = "!VisualStudio.DTE.10.0:" + processId.ToString();
object runningObject = null;
IBindCtx bindCtx = null;
IRunningObjectTable rot = null;
IEnumMoniker enumMonikers = null;
try
{
Marshal.ThrowExceptionForHR(CreateBindCtx(reserved: 0, ppbc: out bindCtx));
bindCtx.GetRunningObjectTable(out rot);
rot.EnumRunning(out enumMonikers);
IMoniker[] moniker = new IMoniker[1];
IntPtr numberFetched = IntPtr.Zero;
while (enumMonikers.Next(1, moniker, numberFetched) == 0)
{
IMoniker runningObjectMoniker = moniker[0];
string name = null;
try
{
if (runningObjectMoniker != null)
{
runningObjectMoniker.GetDisplayName(bindCtx, null, out name);
}
}
catch (UnauthorizedAccessException)
{
// Do nothing, there is something in the ROT that we do not have access to.
}
if (!string.IsNullOrEmpty(name) && string.Equals(name, progId, StringComparison.Ordinal))
{
Marshal.ThrowExceptionForHR(rot.GetObject(runningObjectMoniker, out runningObject));
break;
}
}
}
finally
{
if (enumMonikers != null)
{
Marshal.ReleaseComObject(enumMonikers);
}
if (rot != null)
{
Marshal.ReleaseComObject(rot);
}
if (bindCtx != null)
{
Marshal.ReleaseComObject(bindCtx);
}
}
return (DTE)runningObject;
}
If you know the solution name in advance, you can find it in the MainWindowTitle property of Process and pass the ProcessID to the method above.
var dte = GetDTE(System.Diagnostics.Process.GetProcesses().Where(x => x.MainWindowTitle.StartsWith("SolutionName") && x.ProcessName.Contains("devenv")).FirstOrDefault().Id);
Whilst the above code worked, I encountered a COM error which I fixed by using the MessageFilter class shown here.
From that post, this is what the MessageFilter class looks like
public class MessageFilter : IOleMessageFilter
{
// Class containing the IOleMessageFilter
// thread error-handling functions.
// Start the filter.
public static void Register()
{
IOleMessageFilter newFilter = new MessageFilter();
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(newFilter, out oldFilter);
}
// Done with the filter, close it.
public static void Revoke()
{
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(null, out oldFilter);
}
//
// IOleMessageFilter functions.
// Handle incoming thread requests.
int IOleMessageFilter.HandleInComingCall(int dwCallType,
System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr lpInterfaceInfo)
{
//Return the flag SERVERCALL_ISHANDLED.
return 0;
}
// Thread call was rejected, so try again.
int IOleMessageFilter.RetryRejectedCall(System.IntPtr
hTaskCallee, int dwTickCount, int dwRejectType)
{
if (dwRejectType == 2)
// flag = SERVERCALL_RETRYLATER.
{
// Retry the thread call immediately if return >=0 &
// <100.
return 99;
}
// Too busy; cancel call.
return -1;
}
int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
int dwTickCount, int dwPendingType)
{
//Return the flag PENDINGMSG_WAITDEFPROCESS.
return 2;
}
// Implement the IOleMessageFilter interface.
[DllImport("Ole32.dll")]
private static extern int
CoRegisterMessageFilter(IOleMessageFilter newFilter, out
IOleMessageFilter oldFilter);
}
[ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
interface IOleMessageFilter
{
[PreserveSig]
int HandleInComingCall(
int dwCallType,
IntPtr hTaskCaller,
int dwTickCount,
IntPtr lpInterfaceInfo);
[PreserveSig]
int RetryRejectedCall(
IntPtr hTaskCallee,
int dwTickCount,
int dwRejectType);
[PreserveSig]
int MessagePending(
IntPtr hTaskCallee,
int dwTickCount,
int dwPendingType);
}
Then you can access the project names like this
var dte = GetDTE(System.Diagnostics.Process.GetProcesses().Where(x => x.MainWindowTitle.StartsWith("SolutionName") && x.ProcessName.Contains("devenv")).FirstOrDefault().Id);
MessageFilter.Register();
var projects = dte.Solution.OfType<Project>().ToList();
MessageFilter.Revoke();
foreach (var proj in projects)
{
Debug.WriteLine(proj.Name);
}
Marshal.ReleaseComObject(dte);
I believe you can use something like this:
var dte = (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE));
if (dte != null)
{
var solution = dte.Solution;
if (solution != null)
{
// get your projects here
}
}
I am having an issue working with EnumDisplayDevices in C#. I used the code posted here and it worked seamlessly. However recently I switched to coding the application on my desktop computer. The code no longer works, not giving me anything.
If it helps, my monitor is an LG W2753VC running on an AMD Radeon HD 5770.
Here is my current code:
var device = new DISPLAY_DEVICE();
device.cb = Marshal.SizeOf(device);
try {
for (uint id = 0; EnumDisplayDevices(null, id, ref device, 0); id++) {
device.cb = Marshal.SizeOf(device);
EnumDisplayDevices(device.DeviceName, 0, ref device, 0);
device.cb = Marshal.SizeOf(device);
Console.WriteLine("id={0}, name={1}, devicestring={2}", id, device.DeviceName, device.DeviceString);
if (device.DeviceName == null || device.DeviceName == "") continue;
}
} catch (Exception ex) { }
What I'm getting on my laptop:
id=0, name=\\.\DISPLAY1\Monitor0, devicestring=Generic PnP Monitor
(That should be "Mobile PC Display", but it's not the problem here)
What I'm getting on my desktop:
id=0, name=, devicestring=
id=1, name=, devicestring=
Am I doing this wrong, and if not, is there any other way to get all connected displays? I have already tried the WMI and registry approach.
Hard to tell without you posting all your p/invoke code. Here's code that works on my workstation:
public class EnumDisplayDevicesTest
{
[DllImport("user32.dll")]
static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);
[Flags()]
public enum DisplayDeviceStateFlags : int
{
/// <summary>The device is part of the desktop.</summary>
AttachedToDesktop = 0x1,
MultiDriver = 0x2,
/// <summary>The device is part of the desktop.</summary>
PrimaryDevice = 0x4,
/// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
MirroringDriver = 0x8,
/// <summary>The device is VGA compatible.</summary>
VGACompatible = 0x10,
/// <summary>The device is removable; it cannot be the primary display.</summary>
Removable = 0x20,
/// <summary>The device has more display modes than its output devices support.</summary>
ModesPruned = 0x8000000,
Remote = 0x4000000,
Disconnect = 0x2000000
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DISPLAY_DEVICE
{
[MarshalAs(UnmanagedType.U4)]
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceString;
[MarshalAs(UnmanagedType.U4)]
public DisplayDeviceStateFlags StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceKey;
}
public void Display()
{
DISPLAY_DEVICE d = new DISPLAY_DEVICE();
d.cb = Marshal.SizeOf(d);
try
{
for (uint id = 0; EnumDisplayDevices(null, id, ref d, 0); id++)
{
if (d.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop))
{
Console.WriteLine(
String.Format("{0}, {1}, {2}, {3}, {4}, {5}",
id,
d.DeviceName,
d.DeviceString,
d.StateFlags,
d.DeviceID,
d.DeviceKey
)
);
d.cb = Marshal.SizeOf(d);
EnumDisplayDevices(d.DeviceName, 0, ref d, 0);
Console.WriteLine(
String.Format("{0}, {1}",
d.DeviceName,
d.DeviceString
)
);
}
d.cb = Marshal.SizeOf(d);
}
}
catch (Exception ex)
{
Console.WriteLine(String.Format("{0}", ex.ToString()));
}
}
}
The above code works as the OP desires on my machines, not sure why it won't work on his laptop.
An alternative method to getting the info is listed below, taken from here:
foreach (var display in DisplayDetails.GetMonitorDetails())
{
Console.WriteLine(display.Model);
}
public class DisplayDetails
{
public string PnPID { get; set; }
public string SerialNumber { get; set; }
public string Model { get; set; }
public string MonitorID { get; set; }
/// <summary>
/// The Constructor to create a new instances of the DisplayDetails class...
/// </summary>
public DisplayDetails(string sPnPID, string sSerialNumber, string sModel, string sMonitorID)
{
PnPID = sPnPID;
SerialNumber = sSerialNumber;
Model = sModel;
MonitorID = sMonitorID;
}
/// <summary>
/// This Function returns all Monitor Details
/// </summary>
/// <returns></returns>
static public IEnumerable<DisplayDetails> GetMonitorDetails()
{
//Open the Display Reg-Key
RegistryKey Display = Registry.LocalMachine;
Boolean bFailed = false;
try
{
Display = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Enum\DISPLAY");
}
catch
{
bFailed = true;
}
if (!bFailed & (Display != null))
{
//Get all MonitorIDss
foreach (string sMonitorID in Display.GetSubKeyNames())
{
RegistryKey MonitorID = Display.OpenSubKey(sMonitorID);
if (MonitorID != null)
{
//Get all Plug&Play ID's
foreach (string sPNPID in MonitorID.GetSubKeyNames())
{
RegistryKey PnPID = MonitorID.OpenSubKey(sPNPID);
if (PnPID != null)
{
string[] sSubkeys = PnPID.GetSubKeyNames();
//Check if Monitor is active
if (sSubkeys.Contains("Control"))
{
if (sSubkeys.Contains("Device Parameters"))
{
RegistryKey DevParam = PnPID.OpenSubKey("Device Parameters");
string sSerial = "";
string sModel = "";
//Define Search Keys
string sSerFind = new string(new char[] { (char)00, (char)00, (char)00, (char)0xff });
string sModFind = new string(new char[] { (char)00, (char)00, (char)00, (char)0xfc });
//Get the EDID code
byte[] bObj = DevParam.GetValue("EDID", null) as byte[];
if (bObj != null)
{
//Get the 4 Vesa descriptor blocks
string[] sDescriptor = new string[4];
sDescriptor[0] = Encoding.Default.GetString(bObj, 0x36, 18);
sDescriptor[1] = Encoding.Default.GetString(bObj, 0x48, 18);
sDescriptor[2] = Encoding.Default.GetString(bObj, 0x5A, 18);
sDescriptor[3] = Encoding.Default.GetString(bObj, 0x6C, 18);
//Search the Keys
foreach (string sDesc in sDescriptor)
{
if (sDesc.Contains(sSerFind))
{
sSerial = sDesc.Substring(4).Replace("\0", "").Trim();
}
if (sDesc.Contains(sModFind))
{
sModel = sDesc.Substring(4).Replace("\0", "").Trim();
}
}
}
if (!string.IsNullOrEmpty(sPNPID + sSerFind + sModel + sMonitorID))
{
yield return new DisplayDetails(sPNPID, sSerial, sModel, sMonitorID);
}
}
}
}
}
}
}
}
}
}
I had exactly this behavior when device.cb wasn't equal to one of 840 or 224 (sizeof DISPLAY_DEVICEW and DISPLAY_DEVICEA respectively). In my case I just mistakenly wrote device.cb = sizeof(device.cb);
Check value of Marshal.SizeOf(device) on both your computers.
I had the exact same problem and I found out that I was using the following to import EnumDisplayDevices:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
Rather than
[DllImport("user32.dll")]
The code example from GalacticJello is working for me. I forced the build of the assemblies for x86.
In other cases maybe try:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DISPLAY_DEVICE`
but this is not working for x86!