我知道以提升方式運行的.NET應用程序無法看到用戶的映射驅動器。我也知道有一個註冊表黑客來解決這個問題(這涉及重新啓動)。提升的應用程序需要獲取未提升的映射驅動器列表
我想爲這個問題創建一個不同的解決方案。我們的應用程序必須運行提升,並且嚴重依賴於用戶創建的映射驅動器。我想要檢測用戶擁有的映射驅動器,並從高級應用程序映射出類似的一堆。
所以問題是:如何從高架應用程序中檢測'普通'用戶的映射驅動器?
我知道以提升方式運行的.NET應用程序無法看到用戶的映射驅動器。我也知道有一個註冊表黑客來解決這個問題(這涉及重新啓動)。提升的應用程序需要獲取未提升的映射驅動器列表
我想爲這個問題創建一個不同的解決方案。我們的應用程序必須運行提升,並且嚴重依賴於用戶創建的映射驅動器。我想要檢測用戶擁有的映射驅動器,並從高級應用程序映射出類似的一堆。
所以問題是:如何從高架應用程序中檢測'普通'用戶的映射驅動器?
如果映射驅動器是永久映射(勾選「登錄時重新連接」啓用),則可以在用戶的註冊表配置單元找到它:
HKEY_CURRENT_USER\Network\<drive letter>
那個鍵都有一個值包含UNC路徑RemotePath
。
嗨Helge。這部分註冊表中的條目似乎不是我可以使用的完整映射驅動器集。例如,我可以看到我的O和Y驅動器,但不是我的P.P驅動器是我的主驅動器,它已通過我的域配置文件映射。我猜P驅動器不是持久的,因爲它可能創建每次我登錄。 – flobadob
我現在有幾個解決這個問題的方法。讀取註冊表是可以的,但您不會找到由您的域配置文件或其他臨時映射驅動器創建的驅動器。
我測試過的一個解決方案是使用this代碼創建未升級的過程。我寫了一個簡單的GetMappedDrives.exe應用程序,它將映射的驅動器寫入文件。然後提升的應用程序可以讀取文件以獲取未升級的映射驅動器。
另一種解決方案可能是在升級的應用程序中使用未升高的包裝。未升級的包裝將首先調用GetMappedDrives.exe然後運行提升的應用程序。問題是,除非重新啓動應用程序,否則您將無法瞭解映射驅動器的更改。
如果您碰巧有一個未升級的進程作爲您的應用程序套件的一部分運行,第三種解決方案可能適用。只需從未升級的應用程序中彈出網絡消息,告訴它調用GetMappedDrives.exe即可。
GetMappedDrives C#代碼...
static void Main(string[] args)
{
//if (args.GetLength(0) != 1)
//{
// Debug.Assert(false);
// Console.WriteLine("You must supply the target file path");
// Environment.Exit(1);
//}
//String strTargetPath = args[0];
String strTargetPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\MyCompany\MappedDrives.csv";
FileStream fs = new FileStream(strTargetPath, FileMode.Create, FileAccess.Write);
StreamWriter writer = new StreamWriter(fs);
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo dInfo in allDrives)
{
if (dInfo.DriveType == DriveType.Network || dInfo.DriveType == DriveType.Removable)
{
String s = String.Format("{0},{1},{2},{3},{4}\n", dInfo.Name, dInfo.VolumeLabel, dInfo.DriveType, dInfo.TotalSize, dInfo.AvailableFreeSpace);
writer.Write(s);
}
}
writer.Close();
}
TestGetMappedDrives C++代碼。在提升的命令提示符下運行...
#include "stdafx.h"
#include "windows.h"
//#ifndef SECURITY_MANDATORY_HIGH_RID
// #define SECURITY_MANDATORY_UNTRUSTED_RID (0x00000000L)
// #define SECURITY_MANDATORY_LOW_RID (0x00001000L)
// #define SECURITY_MANDATORY_MEDIUM_RID (0x00002000L)
// #define SECURITY_MANDATORY_HIGH_RID (0x00003000L)
// #define SECURITY_MANDATORY_SYSTEM_RID (0x00004000L)
// #define SECURITY_MANDATORY_PROTECTED_PROCESS_RID (0x00005000L)
//#endif
//#ifndef TokenIntegrityLevel
// #define TokenIntegrityLevel ((TOKEN_INFORMATION_CLASS)25)
//#endif
//#ifndef TOKEN_MANDATORY_LABEL
// typedef struct
// {
// SID_AND_ATTRIBUTES Label;
// } TOKEN_MANDATORY_LABEL;
//#endif
typedef BOOL (WINAPI *defCreateProcessWithTokenW)
(HANDLE,DWORD,LPCWSTR,LPWSTR,DWORD,LPVOID,LPCWSTR,LPSTARTUPINFOW,LPPROCESS_INFORMATION);
// Writes Integration Level of the process with the given ID into pu32_ProcessIL
// returns Win32 API error or 0 if succeeded
DWORD GetProcessIL(DWORD u32_PID, DWORD* pu32_ProcessIL)
{
*pu32_ProcessIL = 0;
HANDLE h_Process = 0;
HANDLE h_Token = 0;
DWORD u32_Size = 0;
BYTE* pu8_Count = 0;
DWORD* pu32_ProcIL = 0;
TOKEN_MANDATORY_LABEL* pk_Label = 0;
h_Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, u32_PID);
if (!h_Process)
goto _CleanUp;
if (!OpenProcessToken(h_Process, TOKEN_QUERY, &h_Token))
goto _CleanUp;
if (!GetTokenInformation(h_Token, TokenIntegrityLevel, NULL, 0, &u32_Size) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto _CleanUp;
pk_Label = (TOKEN_MANDATORY_LABEL*) HeapAlloc(GetProcessHeap(), 0, u32_Size);
if (!pk_Label)
goto _CleanUp;
if (!GetTokenInformation(h_Token, TokenIntegrityLevel, pk_Label, u32_Size, &u32_Size))
goto _CleanUp;
pu8_Count = GetSidSubAuthorityCount(pk_Label->Label.Sid);
if (!pu8_Count)
goto _CleanUp;
pu32_ProcIL = GetSidSubAuthority(pk_Label->Label.Sid, *pu8_Count-1);
if (!pu32_ProcIL)
goto _CleanUp;
*pu32_ProcessIL = *pu32_ProcIL;
SetLastError(ERROR_SUCCESS);
_CleanUp:
DWORD u32_Error = GetLastError();
if (pk_Label) HeapFree(GetProcessHeap(), 0, pk_Label);
if (h_Token) CloseHandle(h_Token);
if (h_Process) CloseHandle(h_Process);
return u32_Error;
}
// Creates a new process u16_Path with the integration level of the Explorer process (MEDIUM IL)
// If you need this function in a service you must replace FindWindow() with another API to find Explorer process
// The parent process of the new process will be svchost.exe if this EXE was run "As Administrator"
// returns Win32 API error or 0 if succeeded
DWORD CreateProcessMediumIL(WCHAR* u16_Path, WCHAR* u16_CmdLine)
{
HANDLE h_Process = 0;
HANDLE h_Token = 0;
HANDLE h_Token2 = 0;
PROCESS_INFORMATION k_ProcInfo = {0};
STARTUPINFOW k_StartupInfo = {0};
BOOL b_UseToken = FALSE;
// Detect Windows Vista, 2008, Windows 7 and higher
if (GetProcAddress(GetModuleHandleA("Kernel32"), "GetProductInfo"))
{
DWORD u32_CurIL;
DWORD u32_Err = GetProcessIL(GetCurrentProcessId(), &u32_CurIL);
if (u32_Err)
return u32_Err;
if (u32_CurIL > SECURITY_MANDATORY_MEDIUM_RID)
b_UseToken = TRUE;
}
// Create the process normally (before Windows Vista or if current process runs with a medium IL)
if (!b_UseToken)
{
if (!CreateProcessW(u16_Path, u16_CmdLine, 0, 0, FALSE, 0, 0, 0, &k_StartupInfo, &k_ProcInfo))
return GetLastError();
CloseHandle(k_ProcInfo.hThread);
CloseHandle(k_ProcInfo.hProcess);
return ERROR_SUCCESS;
}
defCreateProcessWithTokenW f_CreateProcessWithTokenW =
(defCreateProcessWithTokenW) GetProcAddress(GetModuleHandleA("Advapi32"), "CreateProcessWithTokenW");
if (!f_CreateProcessWithTokenW) // This will never happen on Vista!
return ERROR_INVALID_FUNCTION;
HWND h_Progman = ::GetShellWindow();
DWORD u32_ExplorerPID = 0;
GetWindowThreadProcessId(h_Progman, &u32_ExplorerPID);
// ATTENTION:
// If UAC is turned OFF all processes run with SECURITY_MANDATORY_HIGH_RID, also Explorer!
// But this does not matter because to start the new process without UAC no elevation is required.
h_Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, u32_ExplorerPID);
if (!h_Process)
goto _CleanUp;
if (!OpenProcessToken(h_Process, TOKEN_DUPLICATE, &h_Token))
goto _CleanUp;
if (!DuplicateTokenEx(h_Token, TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &h_Token2))
goto _CleanUp;
if (!f_CreateProcessWithTokenW(h_Token2, 0, u16_Path, u16_CmdLine, 0, 0, 0, &k_StartupInfo, &k_ProcInfo))
goto _CleanUp;
SetLastError(ERROR_SUCCESS);
_CleanUp:
DWORD u32_Error = GetLastError();
if (h_Token) CloseHandle(h_Token);
if (h_Token2) CloseHandle(h_Token2);
if (h_Process) CloseHandle(h_Process);
CloseHandle(k_ProcInfo.hThread);
CloseHandle(k_ProcInfo.hProcess);
return u32_Error;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD u32_Err = CreateProcessMediumIL(L"C:\\src\\bin\\release\\GetMappedDrives.exe", NULL);
printf("CreateProcessMediumIL() exited with error %d\r\n", u32_Err);
Sleep(2000);
return 0;
}
什麼 - 我不知道從哪裏開始。我知道如何獲取映射驅動器的列表,但不知道未升級的用戶。 – flobadob
我想我可以從提升的應用程序產生一個未升級的進程,讓他開車列表並將結果存儲在某處。然後提升的應用程序可以讀取列表。這有點哈克,但。想要更好的建議,如果有人有。 – flobadob