これは、リソースファイルを使用する最初の試みです。C#には当てはまるがCには当てはまらない多くの回答を見てきました。何か提案はありますか?
1 に答える
Sysinternalsなどがプログラムのリソースセクション(SysinternalsのProcess Explorerなど)でドライバーまたは必要なDLL(またはプログラム自体のx64バージョン)を運ぶために使用するメソッドを意味すると仮定すると、MicrosoftVisualCを使用して使用できますこのコード:
BOOL ExtractResTo(HINSTANCE Instance, LPCTSTR BinResName, LPCTSTR NewPath, LPCTSTR ResType)
{
BOOL bResult = FALSE;
HRSRC hRsrc;
if(hRsrc = FindResource(HMODULE(Instance), BinResName, ResType))
{
HGLOBAL hGlob
if(HGLOBAL hGlob = LoadResource(Instance, hRsrc))
{
DWORD dwResSize = SizeofResource(Instance, hRsrc);
HANDLE hFileWrite = CreateFile(NewPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0);
if(hFileWrite != INVALID_HANDLE_VALUE)
__try
{
DWORD dwSizeWritten = 0;
bResult = (WriteFile(hFileWrite, LockResource(hGlob), dwResSize, &dwSizeWritten, NULL) && (dwSizeWritten == dwResSize));
}
__finally
{
CloseHandle(hFileWrite);
}
}
}
return bResult;
}
これにより、BinResName
リソースタイプ()の指定されたリソース()がResType
モジュール(DLLなど)Instance
からファイルに保存されますNewPath
。明らかに、Cが理解できない場合は、それに応じてコードを調整する必要が__try
あり__finally
ます。
ここ(で)からSIDT.rar
取得し、C用に調整しました。コードは、WebサイトによるとリベラルなBSDライセンスの下にあります。
ppRes
ここで、データへのポインタ( )とそのサイズ(pwdResSize
)を取得したい場合は、次のようにします。
BOOL GetResourcePointer(HINSTANCE Instance, LPCTSTR ResName, LPCTSTR ResType, LPVOID* ppRes, DWORD* pdwResSize)
{
// Check the pointers to which we want to write
if(ppRes && pdwResSize)
{
HRSRC hRsrc;
// Find the resource ResName of type ResType in the DLL/EXE described by Instance
if(hRsrc = FindResource((HMODULE)Instance, ResName, ResType))
{
HGLOBAL hGlob;
// Make sure it's in memory ...
if(hGlob = LoadResource(Instance, hRsrc))
{
// Now lock it to get a pointer
*ppRes = LockResource(hGlob);
// Also retrieve the size of the resource
*pdwResSize = SizeofResource(Instance, hRsrc);
// Return TRUE only if both succeeded
return (*ppRes && *pdwResSize);
}
}
}
// Failure means don't use the values in *ppRes and *pdwResSize
return FALSE;
}
このように呼び出します:
LPVOID pResource;
DWORD pResourceSize;
if(GetResourcePointer(hInstance, _T("somename"), _T("sometype"), &pResource, &pResourceSize))
{
// use pResource and pResourceSize
// e.g. store into a string buffer or whatever you want to do with it ...
}
これは、整数IDのリソースでも機能することに注意してください。これらは、マクロを使用して検出できますIS_INTRESOURCE
。
myresources.rcなどのリソーススクリプト自体は簡単です。
#include <winnt.rh>
"somename" "sometype" "path\to\file\to\embed"
RCDATA
sometypeの代わりに合理的な選択です
#include <winnt.rh> // for RCDATA to be known to rc.exe
"somename" RCDATA "path\to\file\to\embed"
...この場合、上記の呼び出しを次のように調整します。
GetResourcePointer(hInstance, _T("somename"), RT_RCDATA, &pResource, &pResourceSize)
上記を利用した完全な例GetResourcePointer
。ポインタ変数がchar* buf
あり、リソースが実際のテキストであることがわかっている場合、文字列として使用するときにそれがゼロで終了していることを確認する必要があります。それだけです。
リソーススクリプト:
#include <winnt.rh>
"test" RCDATA "Test.txt"
それにアクセスするコード
char* buf = NULL;
LPVOID pResource;
DWORD pResourceSize;
if(GetResourcePointer(hInstance, _T("test"), RT_RCDATA, &pResource, &pResourceSize))
{
if(buf = calloc(pResourceSize+1, sizeof(char)))
{
memcpy(buf, pResource, pResourceSize);
// Now use buf
free(buf);
}
}
.res
もちろん、リンカのコマンドラインに渡すことで機能するファイルを単にリンクするつもりでない限り。