Impersonation in Windows Server 2008 - c#

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.

Related

get data from printer local port

I have done a virtual printer by using some sample code. But I don't know how to get data from it when it starts printing.
When it starts printing It gives notification that ERROR IN PRITNING.
And Why there is "C:/MyLocalPort.txt".
Anyone Help me to get data this virtual printer sets to print.
Here is the Sample Code:
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Management;
namespace virtualPrinter
{
public static class PrinterClass // class which carries SetDefaultPrinter function
{
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetDefaultPrinter(string Printer);
}
class myPrinterClass
{
public static void getPrinterNames()
{
foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
MessageBox.Show(printer);
}
}
public static void installPrinter(string printerName) //works on win 7,8,8.1,10 on both x84 and x64
{
Winspool.AddLocalPort(#"C:\MyLocalPort.txt");
//https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/rundll32-printui
// /if Installs a printer by using an .inf file.
// /b[name] Specifies the base printer name.
// /#[file] Specifies a command-line argument file and directly inserts the text in that file into the command line.
// /f[file] Species the Universal Naming Convention (UNC) path and name of the .inf file name or the output file name, depending on the task that you are performing. Use /F[file] to specify a dependent .inf file.
// /r[port] Specifies the port name.
// /m[model] Specifies the driver model name. (This value can be specified in the .inf file.)
string arg;
arg = "printui.dll , PrintUIEntry /if /b " + "\"" + printerName + "\"" + #" /f C:\Windows\inf\ntprint.inf /r " + "\"" + #"C:\MyLocalPort.txt" + "\"" + " /m " + "\"" + "Generic / Text Only" + "\""; //initial arg
ProcessStartInfo p = new ProcessStartInfo();
p.FileName = "rundll32.exe";
p.Arguments = arg;
p.WindowStyle = ProcessWindowStyle.Hidden;
try
{
Process.Start(p);
MessageBox.Show(printerName + " installed succesfully!");
}
catch (Exception ex)
{
MessageBox.Show("Something went wrong. Try again!" );
}
}
public static bool printerExists(string printerName)
{
bool res = false;
foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
if (printer == printerName)
{
res = true;
}
}
return res;
}
public static void uninstallPrinter(string printerName)
{
string arg;
ProcessStartInfo p = new ProcessStartInfo();
arg = "printui.dll, PrintUIEntry /dl /n " + "\"" + printerName + "\"";
if (printerExists(printerName))
{
p.FileName = "rundll32.exe";
p.Arguments = arg;
p.WindowStyle = ProcessWindowStyle.Hidden;
try
{
Process.Start(p);
MessageBox.Show(printerName + " unistalled successfully");
}
catch (Exception ex)
{
MessageBox.Show(ex.InnerException.ToString());
}
p = null;
}
}
public static string GetLocalIPAddress() //erxomeno feature
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("No network adapters with an IPv4 address in the system!");
}
public static class Winspool
{
[StructLayout(LayoutKind.Sequential)]
private class PRINTER_DEFAULTS
{
public string pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[DllImport("winspool.drv", EntryPoint = "XcvDataW", SetLastError = true)]
private static extern bool XcvData(
IntPtr hXcv,
[MarshalAs(UnmanagedType.LPWStr)] string pszDataName,
IntPtr pInputData,
uint cbInputData,
IntPtr pOutputData,
uint cbOutputData,
out uint pcbOutputNeeded,
out uint pwdStatus);
[DllImport("winspool.drv", EntryPoint = "OpenPrinterA", SetLastError = true)]
private static extern int OpenPrinter(
string pPrinterName,
ref IntPtr phPrinter,
PRINTER_DEFAULTS pDefault);
[DllImport("winspool.drv", EntryPoint = "ClosePrinter")]
private static extern int ClosePrinter(IntPtr hPrinter);
public static int AddLocalPort(string portName)
{
PRINTER_DEFAULTS def = new PRINTER_DEFAULTS();
def.pDatatype = null;
def.pDevMode = IntPtr.Zero;
def.DesiredAccess = 1; //Server Access Administer
IntPtr hPrinter = IntPtr.Zero;
int n = OpenPrinter(",XcvMonitor Local Port", ref hPrinter, def);
if (n == 0)
return Marshal.GetLastWin32Error();
if (!portName.EndsWith("\0"))
portName += "\0"; // Must be a null terminated string
// Must get the size in bytes. Rememeber .NET strings are formed by 2-byte characters
uint size = (uint)(portName.Length * 2);
// Alloc memory in HGlobal to set the portName
IntPtr portPtr = Marshal.AllocHGlobal((int)size);
Marshal.Copy(portName.ToCharArray(), 0, portPtr, portName.Length);
uint needed; // Not that needed in fact...
uint xcvResult; // Will receive de result here
XcvData(hPrinter, "AddPort", portPtr, size, IntPtr.Zero, 0, out needed, out xcvResult);
ClosePrinter(hPrinter);
Marshal.FreeHGlobal(portPtr);
return (int)xcvResult;
}
}
}
}
Ok, I Can't do this that way.
First I have to create a port monitor I have used mfilemon.dll
Then I created a port with that port monitor
Then Pasted All Driver files in System Driver Dictionary.
Then finally Added Printer And Done.
You can refer this
https://github.com/Gohulan/Virtual-Printer/blob/main/PrinterSetup/SpoolerHelper.cs
This contains all the steps to create a virtual printer to make a print to pdf virtual printer

Is there any function faster than Directory.Delete(path, true) to recursively delete all folder, subfolder and content? [duplicate]

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);
}
}
}

Powershell Using pinvoke and low-level variables

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")

StringBuilder in inlined C# in PowerShell (2.0 and above)

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

I can access a file on a network path, but I cannot save to the same path (C#) (asp.net)

This declaration has no problem accessing the file in my network.
MyApp = new Excel.Application();
MyApp.Visible = false;
MyBook = MyApp.Workbooks.Open("//NetworkFolderPath/File.xlsx"); //This line
MySheet = (Excel.Worksheet)MyBook.Sheets[1];
The problem arises when I am done editing my file and I try to save it, using the "SaveCopyAs()" method.
MyBook.SaveCopyAs("//NetworkFolderPath/File2.xlsx");
MyBook.Close(0);
The Exception I get is
An exception of type 'System.Runtime.InteropServices.COMException' occurred in Application.dll but was not handled in user code
Additional information: Microsoft Excel cannot access the file '//NetworkFolderPath/File2.xlsx'. There are several possible reasons:
1. The file name or path does not exist.
2. The file is being used by another program.
3. The workbook you are trying to save has the same name as a currently open workbook.
For Number 1: The file does exist inside the folderm and I accessed the file via the path, so I have ruled out number 1.
For Number 2: I am not sure if it could be this reason, some explanation would be nice
For Number 3: I have given the workbook a different name, but I am not sure if this will solve the problem.
I am really not sure where to go from here. All help is appreciated.
I've seen this path does not exist error when Offline Files are turned on and there is corruption in the cache. Try resetting the cache using the instructions.
Try this, it saves my 2 weeks effort and the application is saving the pdf on sahredpath with secured id (Credential)
if you have any question please comment below !happy to help you
============================
public class Impersonate
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int LogonUser(string lpszUsername, string lpszDomain, string lpszPassword,
int dwLogonType, int dwLogonProvider, out int phToken);
[DllImport("kernel32.dll")]
private static extern int FormatMessage(int dwFlags, string lpSource, int dwMessageId, int dwLanguageId,
StringBuilder lpBuffer, int nSize, string[] Arguments);
private const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
private const int LOGON32_PROVIDER_DEFAULT = 0;
private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;
private static WindowsImpersonationContext winImpersonationContext = null;
public static void ImpersonateUser(string domain, string userName, string password)
{
//Benutzer einloggen
int userToken = 0;
bool loggedOn = (LogonUser(userName, domain, password, LOGON32_LOGON_NETWORK_CLEARTEXT,
LOGON32_PROVIDER_DEFAULT, out userToken) != 0);
if (loggedOn == false)
{
int apiError = Marshal.GetLastWin32Error();
StringBuilder errorMessage = new StringBuilder(1024);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, null, apiError, 0, errorMessage, 1024, null);
throw new Exception(errorMessage.ToString());
}
WindowsIdentity identity = new WindowsIdentity((IntPtr)userToken);
winImpersonationContext = identity.Impersonate();
}
public static void UndoImpersonation()
{
if (winImpersonationContext != null)
{
winImpersonationContext.Undo();
}
}
}
2. Call Impersonate
Impersonate.ImpersonateUser("domain", "user name", "password");
//Your Code as the new User
DirectoryInfo _dirInfo = new DirectoryInfo(#"file path");
FileInfo[] _files = FileExtension.GetFilesByExtensions(_dirInfo, ".xls", ".xlsx").ToArray();
Impersonate.UndoImpersonation();
==============================
Ref:- https://forums.asp.net/t/2126720.aspx?Access+Denied+while+reading+writing+directory+in+Network+File+Share+through+Service+Account

Categories