最近突发奇想,想做一个刷IP的软件,由于一直使用C#编程,基本框架做起来相当简单,唯一比较郁闷的是c#中没有现成的清除本地cookie和IE临时文件夹的方法(用来清除统计代码的cookies,^_^很邪恶吧),话说回来,c#好用,可惜权限比较低,一些涉及系统内部的操作,只好使用c++和c#混合编程的方法了。
本文中涉及到的dll文件下载
在window xp SP3+vs2008 中测试成功~
如果直接用c++写dll,在c#中调用起来比较麻烦,我选择使用ATL的方式编写一个com库,写好后直接在c#或者其他编程语言(VB,Delphi等)中直接引用库就可以了~
以下代码提供了几个封装好的方法:
- ClearCookie 清除cookie
- ClearInternetTempFile 清除Temporary Internet Files中的临时文件
- ClearSystemTemp 清除系统缓存
- ClearIEUrlHistory 清除IE地址栏历史记录
- ClearAutoFormHistory 清除自动表单记录
- ClearAutoPasswordHistory 清除自动密码记录
- ClearFavoriteFolder 清理收藏夹
- ClearAutoRASHistory 清除ADSL拨号历史记录
随后添加一个ATL 简单对象和一个C++类,ATL对象用来为c#提供接口,c++类则存放基本算法代码。
c++代码中编写了一些辅助函数,用于在ATL中调用
#include "StdAfx.h"
#include "innerapi.h"
innerapi::innerapi(void)
{
}
innerapi::~innerapi(void)
{
}
BOOL innerapi::EmptyDirectory(LPCTSTR szPath, BOOL bDeleteDesktopIni, BOOL bWipeIndexDat)
{
WIN32_FIND_DATA wfd;
HANDLE hFind;
CString sFullPath;
CString sFindFilter;
DWORD dwAttributes = 0;
sFindFilter = szPath;
sFindFilter += _T("\\*.*");
if ((hFind = FindFirstFile(sFindFilter, &wfd)) == INVALID_HANDLE_VALUE)
{
return FALSE;
}
do
{
if (_tcscmp(wfd.cFileName, _T(".")) == 0 ||
_tcscmp(wfd.cFileName, _T("..")) == 0 ||
(bDeleteDesktopIni == FALSE && _tcsicmp(wfd.cFileName, _T("desktop.ini")) == 0))
{
continue;
}
sFullPath = szPath;
sFullPath += _T('\\');
sFullPath += wfd.cFileName;
//去掉只读属性
dwAttributes = GetFileAttributes(sFullPath);
if (dwAttributes & FILE_ATTRIBUTE_READONLY)
{
dwAttributes &= ~FILE_ATTRIBUTE_READONLY;
SetFileAttributes(sFullPath, dwAttributes);
}
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
EmptyDirectory(sFullPath, bDeleteDesktopIni, bWipeIndexDat);
RemoveDirectory(sFullPath);
}
else
{
if (bWipeIndexDat && _tcsicmp(wfd.cFileName, _T("index.dat")) == 0)
{
WipeFile(szPath, wfd.cFileName);
}
DeleteFile(sFullPath);
}
}
while (FindNextFile(hFind, &wfd));
FindClose(hFind);
return TRUE;
}
BOOL innerapi::WipeFile(LPCTSTR szDir, LPCTSTR szFile)
{
CString sPath;
HANDLE hFile;
DWORD dwSize;
DWORD dwWrite;
char sZero[SWEEP_BUFFER_SIZE];
memset(sZero, 0, SWEEP_BUFFER_SIZE);
sPath = szDir;
sPath += _T('\\');
sPath += szFile;
hFile = CreateFile(sPath, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
dwSize = GetFileSize(hFile, NULL);
//skip file header (actually, I don't know the file format of index.dat)
dwSize -= 64;
SetFilePointer(hFile, 64, NULL, FILE_BEGIN);
while (dwSize > 0)
{
if (dwSize > SWEEP_BUFFER_SIZE)
{
WriteFile(hFile, sZero, SWEEP_BUFFER_SIZE, &dwWrite, NULL);
dwSize -= SWEEP_BUFFER_SIZE;
}
else
{
WriteFile(hFile, sZero, dwSize, &dwWrite, NULL);
break;
}
}
CloseHandle(hFile);
return TRUE;
}
BOOL innerapi::DeleteUrlCache(DEL_CACHE_TYPE type)
{
BOOL bRet = FALSE;
HANDLE hEntry;
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry = NULL;
DWORD dwEntrySize;
//delete the files
dwEntrySize = 0;
hEntry = FindFirstUrlCacheEntry(NULL, NULL, &dwEntrySize);
lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];
hEntry = FindFirstUrlCacheEntry(NULL, lpCacheEntry, &dwEntrySize);
if (!hEntry)
{
goto cleanup;
}
do
{
if (type == File &&
!(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
{
DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
}
else if (type == Cookie &&
(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
{
DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
}
dwEntrySize = 0;
FindNextUrlCacheEntry(hEntry, NULL, &dwEntrySize);
delete [] lpCacheEntry;
lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];
}
while (FindNextUrlCacheEntry(hEntry, lpCacheEntry, &dwEntrySize));
bRet = TRUE;
cleanup:
if (lpCacheEntry)
{
delete [] lpCacheEntry;
}
return bRet;
}
BOOL innerapi::RegSetPrivilege(HKEY hKey, LPCTSTR pszSubKey,
SECURITY_DESCRIPTOR* pSD, BOOL bRecursive)
{
BOOL bRet = FALSE;
HKEY hSubKey = NULL;
LONG lRetCode;
LPTSTR pszKeyName = NULL;;
DWORD dwSubKeyCnt;
DWORD dwMaxSubKey;
DWORD dwValueCnt;
DWORD dwMaxValueName;
DWORD dwMaxValueData;
DWORD i;
if (!pszSubKey)
goto cleanup;
// open the key for WRITE_DAC access
lRetCode = RegOpenKeyEx(hKey, pszSubKey, 0, WRITE_DAC, &hSubKey);
if(lRetCode != ERROR_SUCCESS)
goto cleanup;
// apply the security descriptor to the registry key
lRetCode = RegSetKeySecurity(hSubKey,
(SECURITY_INFORMATION)DACL_SECURITY_INFORMATION, pSD);
if( lRetCode != ERROR_SUCCESS )
goto cleanup;
if (bRecursive)
{
// reopen the key for KEY_READ access
RegCloseKey(hSubKey);
hSubKey = NULL;
lRetCode = RegOpenKeyEx(hKey, pszSubKey, 0, KEY_READ, &hSubKey);
if(lRetCode != ERROR_SUCCESS)
goto cleanup;
// first get an info about this subkey ...
lRetCode = RegQueryInfoKey(hSubKey, 0, 0, 0, &dwSubKeyCnt, &dwMaxSubKey,
0, &dwValueCnt, &dwMaxValueName, &dwMaxValueData, 0, 0);
if( lRetCode != ERROR_SUCCESS )
goto cleanup;
// enumerate the subkeys and call RegTreeWalk() recursivly
pszKeyName = new TCHAR [MAX_PATH + 1];
for (i=0 ; i<dwSubKeyCnt; i++)
{
lRetCode = RegEnumKey(hSubKey, i, pszKeyName, MAX_PATH + 1);
if(lRetCode == ERROR_SUCCESS)
{
RegSetPrivilege(hSubKey, pszKeyName, pSD, TRUE);
}
else if(lRetCode == ERROR_NO_MORE_ITEMS)
{
break;
}
}
delete [] pszKeyName ;
}
bRet = TRUE; // indicate success
cleanup:
if (hSubKey)
{
RegCloseKey(hSubKey);
}
return bRet;
}
//判断系统类型
BOOL innerapi::IsWindowsNT()
{
BOOL bRet = FALSE;
BOOL bOsVersionInfoEx;
OSVERSIONINFOEX osvi;
// Try calling GetVersionEx using the OSVERSIONINFOEX structure,
// If that fails, try using the OSVERSIONINFO structure.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
return bRet;
}
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion <= 4)
{
bRet = TRUE;
}
return bRet;
}
BOOL innerapi::IsWindows2k()
{
BOOL bRet = FALSE;
BOOL bOsVersionInfoEx;
OSVERSIONINFOEX osvi;
// Try calling GetVersionEx using the OSVERSIONINFOEX structure,
// If that fails, try using the OSVERSIONINFO structure.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
return bRet;
}
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5)
{
bRet = TRUE;
}
return bRet;
}
BOOL innerapi::GetUserSid(PSID* ppSid)
{
HANDLE hToken;
BOOL bRes;
DWORD cbBuffer, cbRequired;
PTOKEN_USER pUserInfo;
// The User's SID can be obtained from the process token
bRes = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
if (FALSE == bRes)
{
return FALSE;
}
// Set buffer size to 0 for first call to determine
// the size of buffer we need.
cbBuffer = 0;
bRes = GetTokenInformation(hToken, TokenUser, NULL, cbBuffer, &cbRequired);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
return FALSE;
}
// Allocate a buffer for our token user data
cbBuffer = cbRequired;
pUserInfo = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbBuffer);
if (NULL == pUserInfo)
{
return FALSE;
}
// Make the "real" call
bRes = GetTokenInformation(hToken, TokenUser, pUserInfo, cbBuffer, &cbRequired);
if (FALSE == bRes)
{
return FALSE;
}
// Make another copy of the SID for the return value
cbBuffer = GetLengthSid(pUserInfo->User.Sid);
*ppSid = (PSID) HeapAlloc(GetProcessHeap(), 0, cbBuffer);
if (NULL == *ppSid)
{
return FALSE;
}
bRes = CopySid(cbBuffer, *ppSid, pUserInfo->User.Sid);
if (FALSE == bRes)
{
HeapFree(GetProcessHeap(), 0, *ppSid);
return FALSE;
}
bRes = HeapFree(GetProcessHeap(), 0, pUserInfo);
return TRUE;
}
void innerapi::GetSidString(PSID pSid, LPTSTR szBuffer)
{
//convert SID to string
SID_IDENTIFIER_AUTHORITY *psia = ::GetSidIdentifierAuthority( pSid );
DWORD dwTopAuthority = psia->Value[5];
_stprintf(szBuffer, _T("S-1-%lu"), dwTopAuthority);
TCHAR szTemp[32];
int iSubAuthorityCount = *(GetSidSubAuthorityCount(pSid));
for (int i = 0; i<iSubAuthorityCount; i++)
{
DWORD dwSubAuthority = *(GetSidSubAuthority(pSid, i));
_stprintf(szTemp, _T("%lu"), dwSubAuthority);
_tcscat(szBuffer, _T("-"));
_tcscat(szBuffer, szTemp);
}
}
BOOL innerapi::GetOldSD(HKEY hKey, LPCTSTR pszSubKey, BYTE** pSD)
{
BOOL bRet = FALSE;
HKEY hNewKey = NULL;
DWORD dwSize = 0;
LONG lRetCode;
*pSD = NULL;
lRetCode = RegOpenKeyEx(hKey, pszSubKey, 0, READ_CONTROL, &hNewKey);
if(lRetCode != ERROR_SUCCESS)
goto cleanup;
lRetCode = RegGetKeySecurity(hNewKey,
(SECURITY_INFORMATION)DACL_SECURITY_INFORMATION, *pSD, &dwSize);
if (lRetCode == ERROR_INSUFFICIENT_BUFFER)
{
*pSD = new BYTE[dwSize];
lRetCode = RegGetKeySecurity(hNewKey,
(SECURITY_INFORMATION)DACL_SECURITY_INFORMATION, *pSD, &dwSize);
if(lRetCode != ERROR_SUCCESS)
{
delete *pSD;
*pSD = NULL;
goto cleanup;
}
}
else if (lRetCode != ERROR_SUCCESS)
goto cleanup;
bRet = TRUE; // indicate success
cleanup:
if (hNewKey)
{
RegCloseKey(hNewKey);
}
return bRet;
}
BOOL innerapi::CreateNewSD(PSID pSid, SECURITY_DESCRIPTOR* pSD, PACL* ppDacl)
{
BOOL bRet = FALSE;
PSID pSystemSid = NULL;
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
ACCESS_ALLOWED_ACE* pACE = NULL;
DWORD dwAclSize;
DWORD dwAceSize;
// prepare a Sid representing local system account
if(!AllocateAndInitializeSid(&sia, 1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0, &pSystemSid))
{
goto cleanup;
}
// compute size of new acl
dwAclSize = sizeof(ACL) + 2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
GetLengthSid(pSid) + GetLengthSid(pSystemSid);
// allocate storage for Acl
*ppDacl = (PACL)HeapAlloc(GetProcessHeap(), 0, dwAclSize);
if(*ppDacl == NULL)
goto cleanup;
if(!InitializeAcl(*ppDacl, dwAclSize, ACL_REVISION))
goto cleanup;
// if(!AddAccessAllowedAce(pDacl, ACL_REVISION, KEY_WRITE, pSid))
// goto cleanup;
// add current user
dwAceSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid);
pACE = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAceSize);
pACE->Mask = KEY_READ | KEY_WRITE | KEY_ALL_ACCESS;
pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
pACE->Header.AceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
pACE->Header.AceSize = dwAceSize;
memcpy(&pACE->SidStart, pSid, GetLengthSid(pSid));
if (!AddAce(*ppDacl, ACL_REVISION, MAXDWORD, pACE, dwAceSize))
goto cleanup;
// add local system account
HeapFree(GetProcessHeap(), 0, pACE);
pACE = NULL;
dwAceSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSystemSid);
pACE = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAceSize);
pACE->Mask = KEY_READ | KEY_WRITE | KEY_ALL_ACCESS;
pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
pACE->Header.AceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
pACE->Header.AceSize = dwAceSize;
memcpy(&pACE->SidStart, pSystemSid, GetLengthSid(pSystemSid));
if (!AddAce(*ppDacl, ACL_REVISION, MAXDWORD, pACE, dwAceSize))
goto cleanup;
if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
goto cleanup;
if(!SetSecurityDescriptorDacl(pSD, TRUE, *ppDacl, FALSE))
goto cleanup;
bRet = TRUE; // indicate success
cleanup:
if(pACE != NULL)
HeapFree(GetProcessHeap(), 0, pACE);
if(pSystemSid != NULL)
FreeSid(pSystemSid);
return bRet;
}
ATL中的代码
// histroy.cpp : Chistroy 的实现
#include "stdafx.h"
#include "histroy.h"
// Chistroy
STDMETHODIMP Chistroy::ClearCookie(VARIANT_BOOL* ret)
{
// TODO: 在此添加实现代码
TCHAR szPath[MAX_PATH];
api.DeleteUrlCache(api.Cookie);
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_COOKIES, FALSE))
{//得到目录,并清空
api.EmptyDirectory(szPath);
}
return S_OK;
}
STDMETHODIMP Chistroy::ClearInternetTempFile(VARIANT_BOOL* ret)
{
// TODO: 在此添加实现代码
// //清internet临时文件
TCHAR szPath[MAX_PATH];
api.DeleteUrlCache(api.File);
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_INTERNET_CACHE, FALSE))
{ //得到临时目录,并清空它.
api.EmptyDirectory(szPath);
}
return S_OK;
}
STDMETHODIMP Chistroy::ClearSystemTemp(VARIANT_BOOL* ret)
{
// TODO: 在此添加实现代码
// //清系统临时文件夹
TCHAR szPath[MAX_PATH];
if (GetTempPath(MAX_PATH, szPath))//得到系统临时目录
{
api.EmptyDirectory(szPath, TRUE);
}
return S_OK;
}
STDMETHODIMP Chistroy::ClearIEUrlHistory(VARIANT_BOOL* ret)
{
//浏览器地址栏历史地址的清除
SHDeleteKey(HKEY_CURRENT_USER,
_T("Software\\Microsoft\\Internet Explorer\\TypedURLs"));
return S_OK;
}
STDMETHODIMP Chistroy::ClearAutoFormHistory(VARIANT_BOOL* ret)
{
// 清除表单自动完成历史记录
CString sKey;
DWORD dwRet;
if (api.IsWindows2k() || api.IsWindowsNT())//先判断系统
{
CString sBaseKey;
SECURITY_DESCRIPTOR NewSD;
BYTE* pOldSD;
PACL pDacl = NULL;
PSID pSid = NULL;
TCHAR szSid[256];
if (api.GetUserSid(&pSid))
{
//get the hiden key name
api.GetSidString(pSid, szSid);
sKey = _T("Software\\Microsoft\\Protected Storage System Provider\\");
sKey += szSid;
//get old SD
sBaseKey = sKey;
api.GetOldSD(HKEY_CURRENT_USER, sBaseKey, &pOldSD);
//set new SD and then clear
if (api.CreateNewSD(pSid, &NewSD, &pDacl))
{
api.RegSetPrivilege(HKEY_CURRENT_USER, sKey, &NewSD, FALSE);
sKey += _T("\\Data");
api.RegSetPrivilege(HKEY_CURRENT_USER, sKey, &NewSD, FALSE);
sKey += _T("\\e161255a-37c3-11d2-bcaa-00c04fd929db");
api.RegSetPrivilege(HKEY_CURRENT_USER, sKey, &NewSD, TRUE);
dwRet = SHDeleteKey(HKEY_CURRENT_USER, sKey);
}
if (pDacl != NULL)
HeapFree(GetProcessHeap(), 0, pDacl);
//restore old SD
if (pOldSD)
{
api.RegSetPrivilege(HKEY_CURRENT_USER, sBaseKey,
(SECURITY_DESCRIPTOR*)pOldSD, FALSE);
delete pOldSD;
}
}
if (pSid)
HeapFree(GetProcessHeap(), 0, pSid);
}
//win9x
DWORD dwSize = MAX_PATH;
TCHAR szUserName[MAX_PATH];
GetUserName(szUserName, &dwSize);
sKey = _T("Software\\Microsoft\\Protected Storage System Provider\\");
sKey += szUserName;
sKey += _T("\\Data\\e161255a-37c3-11d2-bcaa-00c04fd929db");
dwRet = SHDeleteKey(HKEY_LOCAL_MACHINE, sKey);
return S_OK;
}
STDMETHODIMP Chistroy::ClearAutoPasswordHistory(VARIANT_BOOL* ret)
{
// 清除自动密码历史记录
SHDeleteKey(HKEY_CURRENT_USER,
_T("Software\\Microsoft\\Internet Explorer\\IntelliForms"));
return S_OK;
}
STDMETHODIMP Chistroy::ClearFavoriteFolder(VARIANT_BOOL* ret)
{
//清收藏夹中的内容
TCHAR szPath[MAX_PATH];
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, FALSE))
{ //得到目录,并清空
api.EmptyDirectory(szPath);
}
return S_OK;
}
STDMETHODIMP Chistroy::ClearAutoRASHistory(VARIANT_BOOL* ret)
{
// 清RAS自动拨号历史记录
SHDeleteKey(HKEY_CURRENT_USER,
_T("Software\\Microsoft\\RAS Autodial\\Addresses"));
return S_OK;
}
可以在c#中直接调用就可以了
最后提供一个dll文件下载








怎么添加引用都添加不成功啊?报错:Please make sure that the file is accessible,and that it is a valid assembly or COM component
| 2010年12月20日 @ 8:01 下午
已经解决了
| 2010年12月20日 @ 8:10 下午
那就好^_^
| 2010年12月21日 @ 8:24 下午
您好,我想请问一下,这个dll如何在c#中使用啊,请高指教!
| 2011年02月16日 @ 3:42 上午
c#中直接添加引用就可以了
| 2011年02月25日 @ 9:08 上午
我想在C#里加reference,但添加不成功, 报错:Please make sure that the file is accessible,and that it is a valid assembly or COM component.
Shinely, 怎么做的阿???
| 2011年03月31日 @ 8:38 下午
要先注册控件滴^_^
| 2011年04月1日 @ 8:23 上午
请问下,添加成功后,在自己写的程序里,应该怎么用呢?本人是菜鸟,请多指教,谢谢
| 2011年10月18日 @ 3:11 下午
需要在Visual Studio的项目中点击“引用”在对话框中浏览选择指定dll文件就可以了。
| 2011年10月18日 @ 4:37 下午
额 我的意思是 添加引用 成功后, 怎样在我写的代码里使用 你封装好的那些方法,能否请你指导下具体的步骤,谢谢拉
| 2011年10月19日 @ 12:43 上午
呵呵,用法很简单啦,我已经更新了文章,你看下最后一张图,如果无法引用请使用regsvr32注册一下控件
| 2011年10月19日 @ 1:51 下午
谢谢 博主,已经会用了,无以为报,就帮你点点广告啦,呵呵
2011年10月19日 @ 2:20 下午