The C# I am trying to inline is at the bottom, but my error is occurring at the second DllImport, because StringBuilder is not loaded. I have tried a number of things with regards to loading assemblies, adding Using references in the C#, etc. This being one example. But nothing is working and I am pretty sure I am just missing something very obvious to C# programmers, and totally non obvious to my brain.
$assemblies = ('mscorlib.dll')
$code = #'
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);
public static class PxTest
{
// Note
}
'#
Add-Type -memberDefinition $code -referencedAssemblies $assemblies -namespace Px -name Test -errorAction stop
I have also tried $assemblies = ('system.text') which then tries to load system.text.dll that isn't found. Which is what sent me to the dll above, which is where StringBuilder is found I believe.
C# code to ultimately use
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);
public static bool PinUnpinTaskbar(string filePath, bool pin)
{
if (!File.Exists(filePath)) throw new FileNotFoundException(filePath);
int MAX_PATH = 255;
var actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
IntPtr hShell32 = LoadLibrary("Shell32.dll");
LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
string localizedVerb = szPinToStartLocalized.ToString();
string path = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileName(filePath);
// create the shell application object
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
dynamic directory = shellApplication.NameSpace(path);
dynamic link = directory.ParseName(fileName);
dynamic verbs = link.Verbs();
for (int i = 0; i < verbs.Count(); i++)
{
dynamic verb = verbs.Item(i);
if (verb.Name.Equals(localizedVerb))
{
verb.DoIt();
return true;
}
}
return false;
}
EDIT: Trying to understand the edits. I get the added tags, but replacing some body text with... the same text? That I don't get. And that's at least what I am seeing. StringBuilder is is replaced with StringBuilder is, etc. huh?
It is because StringBuilder is not fully qualified and / or the namespace System.Text is not used
So either change the parameter to
System.Text.StringBuilder lpBuffer
or add the UsingNamespace parameter to the Add-Type cmdlet
Add-Type -memberDefinition $code -referencedAssemblies $assemblies -namespace Px -UsingNamespace 'System.Text' -name Test -errorAction stop
As your environment is fixed to PoSh 2.0 and Win7 I rewrote the code to handle the dynamic stuff via PowerShell (which is anyway more idiomatic in this case) and to get the localized verb via the C# code you provided so finally it looks like this which provides you a convenient PowerShell function PinUnpinTaskbar
$assemblies = ('mscorlib.dll')
$code = #'
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);
public static string GetLocalizedPinToStartVerb(bool pin)
{
int MAX_PATH = 255;
int actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
IntPtr hShell32 = LoadLibrary("Shell32.dll");
LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
return szPinToStartLocalized.ToString();
}
'#
Add-Type -MemberDefinition $code `
-ReferencedAssemblies $assemblies `
-Namespace Px `
-UsingNamespace 'System.Text' `
-Name Helper `
-ErrorAction stop
function PinUnpinTaskbar([string]$FilePath, [boolean]$Pin) {
if (Test-Path $FilePath) {
$localizedVerb = [Px.Helper]::GetLocalizedPinToStartVerb($Pin)
$path = [IO.Path]::GetDirectoryName($FilePath)
$fileName = [IO.Path]::GetFileName($FilePath)
$shellAppType = [Type]::GetTypeFromProgID("Shell.Application")
$shellAppInst = [Activator]::CreateInstance($shellAppType)
$directory = $shellAppInst.NameSpace($path)
$link = $directory.ParseName($fileName)
$verbs = $link.Verbs()
for ($i = 0; $i -lt $verbs.Count; ++$i) {
$verb = $verbs.Item($i)
Write-Host $verb.Name
if ($verb.Name.Equals($localizedVerb)) {
$verb.DoIt()
return $true
}
}
return $false
}
else {
Write-Error "File '$FilePath' does not exist"
}
}
Script in action on a vanilla Win7 machine
Related
How to use powershell send a message to a window Control? I have a send example under C#, but I don't know how to write code in powershell.
//using System.Runtime.InteropServices;
[DllImport("user32.dll", EntryPoint = "SendMessageW", CharSet = CharSet.Unicode)]
internal static extern IntPtr SendMessageS(IntPtr hWnd, int Msg, uint wParam, string lParam);
[DllImport("user32.dll", EntryPoint = "FindWindowW", CharSet = CharSet.Unicode)]
internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
static void TestQm2SendMessage()
{
var hwnd = FindWindow("QM_Editor", null);
if(hwnd == default(IntPtr)) return;
SendMessageS(hwnd, 12, 1, "Q ' M 'Macro295' C test C#");
}
I tried to convert C# code to powershell code, but it didn't work. Any suggestions are welcome
$code = #'
[DllImport("user32.dll", EntryPoint = "SendMessageW", CharSet = CharSet.Unicode)] public static extern IntPtr SendMessageS(IntPtr hWnd, int Msg, uint wParam, string lParam);
[DllImport("user32.dll", EntryPoint = "FindWindowW", CharSet = CharSet.Unicode)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
'#
$myAPI = Add-Type -MemberDefinition $code -Name myAPI -PassThru
$myAPI::SendMessageS($myAPI::FindWindow("QM_Editor", $Null), 12, 1, "Q ' M 'Macro295' C test C#");
Found on the Internet
function Out-Notepad
{
param
(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[String]
[AllowEmptyString()]
$Text
)
begin
{
$sb = New-Object System.Text.StringBuilder
}
process
{
$null = $sb.AppendLine($Text)
}
end
{
$text = $sb.ToString()
$process = Start-Process notepad -PassThru
$null = $process.WaitForInputIdle()
$sig = '
[DllImport("user32.dll", EntryPoint = "FindWindowEx")] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll")] public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
'
$type = Add-Type -MemberDefinition $sig -Name APISendMessage -PassThru
$hwnd = $process.MainWindowHandle
[IntPtr]$child = $type::FindWindowEx($hwnd, [IntPtr]::Zero, "Edit", $null)
$null = $type::SendMessage($child, 0x000C, 0, $text)
}
}
#Get-Content -Path 'С:\Folder\File.txt' | Out-String | Out-Notepad
'Send this text to Notepad' | Out-Notepad
You can use .NET System.Windows.Forms.MessageBox. This will also work in Powershell.
[System.Windows.Forms.MessageBox]::Show("Your message here!", 'This is my title', 'YesNo', 'Information')
I have a folder in Windows Server with subfolders and ≈50000 files. When I click the right mouse button and choose delete (or shift+delete) – all files are deleted in 10-20 seconds.
When I delete files using code – 1500-4000 seconds.
Delete large number of files – don't work for me.
My code:
string folderPath = #"C://myFolder";
DirectoryInfo folderInfo = new DirectoryInfo(folderPath);
folderInfo.Delete(true); // true - recursive, with sub-folders
How to delete files faster?
A much faster way to delete files is to use the Windows functions instead of the .NET ones.
You will need to first import the function:
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteFile(string lpFileName);
And then you can do this:
string[] files = Directory.EnumerateFiles(path, "*". SearchOption.AllDirectories);
foreach (string file in files)
{
DeleteFile(file);
}
Once the files are deleted, which is the slowest part by using the managed APIs, you can call Directory.DeleteFolder(path, true) to delete the empty folders.
Since the question is actually about deleting network shared folders and it's stated that the explorer based delete is much faster than the C# internal delete mechanism, it might help to just invoke a windows shell based delete.
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C rd /s /q \"<your-path>\"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
Ofcourse, you have to replace <your-path>.
However, I don't have the infrastructure and files available to test the performance myself right now.
Not quite sure why the method DirectoryInfo.Delete() takes too much time when deleting folders that have a lot of files and sub-folders. I suspect that the method may also do quite a few things that are unnecessary.
I write a small class to to use Win API without doing too many unnecessary things to test my idea. It takes about 40 seconds to delete a folder that have 50,000 files and sub-folders. So, hope it helps.
I use this PowerScript to generate the testing files.
$folder = "d:\test1";
For ($i=0; $i -lt 50000; $i++)
{
New-Item -Path $folder -Name "test$i.txt" -ItemType "file" -Value $i.ToString();
}
The following is the code in C#.
using System;
using System.Collections.Generic;
//
using System.Runtime.InteropServices;
using System.IO;
//
namespace TestFileDelete
{
class FileDelete
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct WIN32_FIND_DATAW
{
public FileAttributes dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public UInt32 nFileSizeHigh; // DWORD
public UInt32 nFileSizeLow; // DWORD
public UInt32 dwReserved0; // DWORD
public UInt32 dwReserved1; // DWORD
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public String cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public String cAlternateFileName;
};
static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr FindFirstFileW(String lpFileName, out WIN32_FIND_DATAW lpFindFileData);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern Boolean FindNextFileW(IntPtr hFindFile, out WIN32_FIND_DATAW lpFindFileData);
[DllImport("kernel32.dll")]
private static extern Boolean FindClose(IntPtr handle);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean DeleteFileW(String lpFileName); // Deletes an existing file
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern Boolean RemoveDirectoryW(String lpPathName); // Deletes an existing empty directory
// This method check to see if the given folder is empty or not.
public static Boolean IsEmptyFolder(String folder)
{
Boolean res = true;
if (folder == null && folder.Length == 0)
{
throw new Exception(folder + "is invalid");
}
WIN32_FIND_DATAW findFileData;
String searchFiles = folder + #"\*.*";
IntPtr searchHandle = FindFirstFileW(searchFiles, out findFileData);
if (searchHandle == INVALID_HANDLE_VALUE)
{
throw new Exception("Cannot check folder " + folder);
}
do
{
if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
{
// found a sub folder
if (findFileData.cFileName != "." && findFileData.cFileName != "..")
{
res = false;
break;
}
} // if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
else
{
// found a file
res = false;
break;
}
} while (FindNextFileW(searchHandle, out findFileData));
FindClose(searchHandle);
return res;
} // public static Boolean IsEmptyFolder(String folder)
// This method deletes the given folder
public static Boolean DeleteFolder(String folder)
{
Boolean res = true;
// keep non-empty folders to delete later (after we delete everything inside)
Stack<String> nonEmptyFolder = new Stack<String>();
String currentFolder = folder;
do
{
Boolean isEmpty = false;
try
{
isEmpty = IsEmptyFolder(currentFolder);
}
catch (Exception ex)
{
// Something wrong
res = false;
break;
}
if (!isEmpty)
{
nonEmptyFolder.Push(currentFolder);
WIN32_FIND_DATAW findFileData;
IntPtr searchHandle = FindFirstFileW(currentFolder + #"\*.*", out findFileData);
if (searchHandle != INVALID_HANDLE_VALUE)
{
do
{ // for each folder, find all of its sub folders and files
String foundPath = currentFolder + #"\" + findFileData.cFileName;
if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
{
// found a sub folder
if (findFileData.cFileName != "." && findFileData.cFileName != "..")
{
if (IsEmptyFolder(foundPath))
{ // found an empty folder, delete it
if (!(res = RemoveDirectoryW(foundPath)))
{
Int32 error = Marshal.GetLastWin32Error();
break;
}
}
else
{ // found a non-empty folder
nonEmptyFolder.Push(foundPath);
}
} // if (findFileData.cFileName != "." && findFileData.cFileName != "..")
} // if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
else
{
// found a file, delete it
if (!(res = DeleteFileW(foundPath)))
{
Int32 error = Marshal.GetLastWin32Error();
break;
}
}
} while (FindNextFileW(searchHandle, out findFileData));
FindClose(searchHandle);
} // if (searchHandle != INVALID_HANDLE_VALUE)
}// if (!IsEmptyFolder(folder))
else
{
if (!(res = RemoveDirectoryW(currentFolder)))
{
Int32 error = Marshal.GetLastWin32Error();
break;
}
}
if (nonEmptyFolder.Count > 0)
{
currentFolder = nonEmptyFolder.Pop();
}
else
{
currentFolder = null;
}
} while (currentFolder != null && res);
return res;
} // public static Boolean DeleteFolder(String folder)
};
class Program
{
static void Main(string[] args)
{
DateTime t1 = DateTime.Now;
try
{
Boolean b = FileDelete.DeleteFolder(#"d:\test1");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
DateTime t2 = DateTime.Now;
TimeSpan ts = t2 - t1;
Console.WriteLine(ts.Seconds);
}
}
}
I'm trying to create a script in PowerShell that extracts [ProductCode] from .msi package located somewhere on disk. I found that I need to use next two methods: MsiOpenPackage and MsiGetProperty. Based on that, I wrote next code snippet:
$signature_GetProperty = #'
[DllImport("msi.dll", CharSet=CharSet.Unicode)]
public static extern int MsiGetProperty(
int hInstall,
string szName,
[Out] StringBuilder szValueBuf,
ref int pchValueBuf);
'#
$signature_OpenPackage = #'
[DllImport("msi.dll", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 MsiOpenPackageEx(
string szPackagePath,
UInt32 dwOptions,
void **hProduct);
'#
$OpenPackageType = Add-Type -MemberDefinition $signature_OpenPackage -Name "WinMsiOpenPackageEX" -Namespace Win32Functions -PassThru
$OpenPackageType::MsiOpenPackageEx($path, 1, STRUGGLING HERE)
$GetInfoType = Add-Type -MemberDefinition $signature_GetProperty -Name "WinGetProperty" -Namespace Win32GetProductCodeMSI -Using System.Text -PassThru
$GetInfoType::MsiGetProperty(AND HERE, "ProductCode",
I'm struggling with how should I declare and use variables that are defined as parameters MsiGetProperty and MsiOpenPackageEx.
For instance, last parameter in OpenPackage is void **hProduct. How should I declare it in .ps1 script in order to use later within MsiGetProperty function. The same goes with ref int pchValueBuf.
I'm sorry for such a lame question, but I would really appreciate any help or clarification or article to read about this type of issue.
Here's a snippet we're using internally:
Add-Type -TypeDefinition #"
using System;
using System.Runtime.InteropServices;
using System.Text;
public static class Msi
{
public static string GetProductVersion(string fileName)
{
IntPtr hInstall = IntPtr.Zero;
try
{
uint num = MsiOpenPackage(fileName, ref hInstall);
if ((ulong)num != 0)
{
throw new Exception("Cannot open database: " + num);
}
int pcchValueBuf = 255;
StringBuilder szValueBuf = new StringBuilder(255);
num = MsiGetProperty(hInstall, "ProductVersion", szValueBuf, ref pcchValueBuf);
if ((ulong)num != 0)
{
throw new Exception("Failed to Get Property ProductVersion: " + num);
}
return szValueBuf.ToString();
}
finally
{
if(hInstall != IntPtr.Zero)
{
MsiCloseHandle(hInstall);
}
}
}
[DllImport("msi.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern int MsiCloseHandle(IntPtr hAny);
[DllImport("msi.dll", CharSet = CharSet.Unicode, EntryPoint = "MsiOpenPackageW", ExactSpelling = true, SetLastError = true)]
private static extern uint MsiOpenPackage(string szDatabasePath, ref IntPtr hProduct);
[DllImport("msi.dll", CharSet = CharSet.Unicode, EntryPoint = "MsiGetPropertyW", ExactSpelling = true, SetLastError = true)]
private static extern uint MsiGetProperty(IntPtr hInstall, string szName, [Out] StringBuilder szValueBuf, ref int pchValueBuf);
}
"#
[Msi]::GetProductVersion("R:\PathTo.msi")
I'm having trouble getting my range exported to an emf file. It does get copied to the clipboard because I can paste it after the exception is thrown:
An exception of type 'System.NullReferenceException' occurred in
N1Narrator.dll but was not handled in user code Additional
information: Object reference not set to an instance of an object.
<--referencing 'img'
Here's my code:
if (intersectRange != null && name.RefersToRange.Cells.Count > 1)
{
name.RefersToRange.CopyPicture(Excel.XlPictureAppearance.xlScreen, Excel.XlCopyPictureFormat.xlPicture);
const int CF_ETAFILE = 14;
IntPtr intptr;
System.Drawing.Imaging.Metafile myMetaFile = null;
if (ClipboardFunctions.OpenClipboard(IntPtr.Zero))
{
if (ClipboardFunctions.IsClipboardFormatAvailable(CF_ETAFILE) != 0)
{
intptr = ClipboardFunctions.GetClipboardData(CF_ETAFILE);
myMetaFile = new Metafile(intptr, true);
ClipboardFunctions.CloseClipboard();
myMetaFile.Save(#"C:\Users\Nick\AppData\Local\Temp\Narrative1\N1Appraisal\ExcelTables\testtable.emf", ImageFormat.Emf);
}
}
}
I've looked into DataObject() as well for the Clipboard but to no avail. I don't want to use the Chart method, it'll be too slow.
Assuming the problem is using an Image datatype to save an EMF vector image not a bitmap from the Clipboard, you can use this code :
//using System.Runtime.InteropServices;
public class ClipboardFunctions
{
[DllImport("user32.dll", EntryPoint = "OpenClipboard", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenClipboard(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "EmptyClipboard", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EmptyClipboard();
[DllImport("user32.dll", EntryPoint = "SetClipboardData", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr SetClipboardData(int uFormat, IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "CloseClipboard", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool CloseClipboard();
[DllImport("user32.dll", EntryPoint = "GetClipboardData", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr GetClipboardData(int uFormat);
[DllImport("user32.dll", EntryPoint = "IsClipboardFormatAvailable", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern short IsClipboardFormatAvailable(int uFormat);
}
private void button1_Click(object sender, EventArgs e)
{
const int CF_ETAFILE = 14;
IntPtr intptr;
System.Drawing.Imaging.Metafile myMetaFile = null;
if (ClipboardFunctions.OpenClipboard(this.Handle))
{
if (ClipboardFunctions.IsClipboardFormatAvailable(CF_ETAFILE) != 0)
{
intptr = ClipboardFunctions.GetClipboardData(CF_ETAFILE);
myMetaFile = new System.Drawing.Imaging.Metafile(intptr, true);
ClipboardFunctions.CloseClipboard();
myMetaFile.Save(#"c:\test.jpg", ImageFormat.Jpeg);
}
}
}
Here is a similar question/answer.
If you're not sure what format the image inside Excel is, then instead of calling Clipboard.GetImage(), try calling Clipboard.GetDataObject()
This returns an IDataObject, which you can in turn query by calling dataObject.GetFormats(). GetFormats() returns the type formats supported by the Clipboard object - there may be a more precise format supported that you can use to extract the data (but I am pretty sure Excel does use EMF for graphs).
Forgive me for my lack of skills in Stackoverflow comments.
sel.CopyPicture(Appearance: Excel.XlPictureAppearance.xlScreen, Format: Excel.XlCopyPictureFormat.xlBitmap);
var image = System.Windows.Forms.Clipboard.GetImage();
This code works fine for me for Excel 2013 addin. Notice I am using xlBitmap instead of xlPicture. Does this meet your requirements? Or I will give a try with xlPicture as well.
I am trying to impersonate a specific user to perform some sql operations in our server. This is not a ASP.Net application. I used the provided code before and it worked. But, recently we have upgraded our environment from windows server 2000 to windows server 2008 R2. After that upgrade this code is not working for me. I need some help in understanding this problem and help solving it. Any and every help will be appreciated. Thanks.
The provided code is a pseudo code, trying to write to a file and do a sql operation.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
using System.Security.Principal;
using System.Security.Permissions;
[assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode = true)]
[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")]
public class Test
{
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_UNLOCK = 7;
const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int SecurityImpersonation = 2;
[DllImport("advapi32.dll", SetLastError = true)]
public static extern int LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken
);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern int ImpersonateLoggedOnUser(
IntPtr hToken
);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RevertToSelf();
[DllImport("kernel32.dll", SetLastError = true)]
static extern int CloseHandle(IntPtr hObject);
public void TestImpersonation()
{
IntPtr lnToken = new IntPtr(0);
IntPtr dupeTokenHandle = new IntPtr(0);
StringBuilder sb = new StringBuilder();
int TResult = LogonUser("itservices", "DFC", "St4hls345t", LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT, out lnToken);
if (TResult > 0)
{
bool retVal = DuplicateToken(lnToken, SecurityImpersonation, ref dupeTokenHandle);
if (false == retVal)
{
CloseHandle(lnToken);
Console.WriteLine("Exception thrown in trying to duplicate token.");
return;
}
WindowsIdentity newId = new WindowsIdentity(dupeTokenHandle);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
writeLog(DateTime.Now.ToString(#"MM-dd-yyyy HH:mm:ss") + " - Impersonation Applied" + Environment.NewLine);
runQuery();
impersonatedUser.Undo();
writeLog(DateTime.Now.ToString(#"MM-dd-yyyy HH:mm:ss") + " - Impersonation Reverted" + Environment.NewLine);
runQuery();
CloseHandle(lnToken);
}
else
{
writeLog(DateTime.Now.ToString(#"MM-dd-yyyy HH:mm:ss") + " - Impersonation not Applied" + Environment.NewLine);
}
return;
}
void writeLog(string message)
{
try
{
string filePath = #"E:\Impersonate\Testlog.txt";
File.AppendAllText(filePath, message);
}
catch
{
Console.WriteLine();
}
}
void runQuery()
{
SQLOperations sqlUtill = new SQLOperations();
string cmdTxt = "SELECT * FROM [tblChildOrder] where [StahlsWorkOrderID] = 'DREAMFUL0015799'";
DataTable dt = sqlUtill.executeQuery(cmdTxt);
if (dt != null)
{
Console.WriteLine();
}
else
{
Console.WriteLine();
}
}
}
Most upgrade that broke my code usually was caused by the upgrade changing permission to users. Double check the users, the permission they have and you should find the problem.