Open sashi0034 opened 2 months ago
Siv3D 側で回避するためには、プログラムが JetBrains Rider によって実行されているかを判定できる必要があります。
次のコードはプログラムの環境変数を出力するコードです。
#include <iostream>
#include <cstdlib>
int main()
{
extern char** environ;
for (int i = 0; environ[i] != nullptr; ++i)
{
std::cout << environ[i] << '\n';
}
}
Visual Studio によって実行した場合、システム環境変数とは別に VisualStudioVersion
などの環境変数が表示され、Visual Studio から起動されたことがわかります。
同様に JetBrains Rider で実行したときにだけ設定される環境変数があれば、System::IsRunningInJetBrainsRider()
を実装でき、問題を回避できます。
なお、v0.6 世代でも v0.6.15 からは v8 と同じ仕様になっています。engine フォルダの内容を Resource.rc で実行ファイルに埋め込んでいるので、カレントディレクトリの影響を受けず、エンジン初期化には成功します。
ありがとうございます。頂いたコードをもとに JetBrains Rider で実行してみましたが、Visual Studio とは異なり、デバッグ実行時に実行環境を表す特有の環境変数が存在しないことが分かりました。
参考までに、ユーザー側で可能な回避策がありました。あらかじめ Run Configuration の Environment variables に VisualStudioVersion のダミーの値を入れておくという方法です。
.vcxproj
ファイル内に環境変数 SIV3D_APP_LAUNCHED_FROM_IDE=1
を追加し、VisualStudioVersion
ではなく SIV3D_APP_LAUNCHED_FROM_IDE
の有無で判定するよう仕様を変更してみました。
JetBrains Rider にも上記設定がインポートされるかはわかりませんが、今後は SIV3D_APP_LAUNCHED_FROM_IDE=1
で対応する予定です。
ご対応ありがとうございます。
しかしながら、Rider では LocalDebuggerCommandArguments
や LocalDebuggerWorkingDirectory
などは反映が可能であるのにも関わらず、LocalDebuggerEnvironment
は扱えないようでデバッグ実行時に SIV3D_APP_LAUNCHED_FROM_IDE=1
が設定されませんでした。
MSVC においても、最初 LocalDebuggerEnvironment
は反映されなかったのですが、
MSVC を起動したときに Siv3D-Test.vcxproj
と同じフォルダに自動的に生成されるローカルファイル Siv3D-Test.vcxproj.user
を一旦削除して再起動したところ反映されました。設定が .user
によってオーバーライドされていたようです。
もしかしたら Rider でも Siv3D-Test.vcxproj.user
が悪さをしているかもしれません。
確かに、ローカル環境のキャッシュの問題であるという可能性は盲点でした
しかし、改めてリポジトリを別フォルダにクローンし直してブランチ v8_develop_0706 に切り替えてから起動・実行してみたのですが、やはり依然として環境変数が設定されないようでした
どうにも、Rider は VisualStudio で設定された LocalDebuggerEnvironment を取り込むことが出来なさそうです
確認ありがとうございます。そうでしたか。 何か別の良い対処法が見つかった場合は対応できるのでお知らせください。
Win32 API で IsDebuggerPresent
という関数があることが分かりました。これを使用すれば、VisualStudio でも Rider でもデバッグ実行時かどうかを実際に検出できました
https://learn.microsoft.com/ja-jp/windows/win32/api/debugapi/nf-debugapi-isdebuggerpresent
標準機能で言うならば std::is_debugger_present
が C++26 に採択されるみたいですね
提案書 にはどういったものが現在利用可能か書いてあるので参考までにどうぞ
IsDebuggerPresent()
は、MSVC で「デバッグなしで開始」から実行すると false になるため、完全な判定には使えなかったと記憶しています。Rider の場合はどうでしょうか。
でも無策よりは Rider での実行に役立つので、IDE 利用判定条件に追加したいと思います。
確かに、Rider でも「(デバッグ無しの) Run」をすると IsDebuggerPresent()
が false になってしまいました...難しいですね
ひとまず対応ありがとうございます
親プロセスの名前を調べることで、Rider からの起動を判定できそうでした。 ただ、この処理にはかなりの時間(10 ms 程度)がかかります。 エンジン初期化が遅くなってしまうため、Siv3D 本体への採用は不可能です。
# include <Siv3D.hpp> // Siv3D v0.8.0
# include <Siv3D/Windows/Windows.hpp>
# include <tlhelp32.h>
struct ProcessInfo
{
DWORD pid = 0;
String name;
};
Optional<ProcessInfo> GetParentProcess(DWORD processID)
{
HANDLE hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
return none;
}
PROCESSENTRY32W pe32
{
.dwSize = sizeof(PROCESSENTRY32W)
};
ProcessInfo parentInfo;
if (::Process32FirstW(hSnapshot, &pe32))
{
do
{
if (pe32.th32ProcessID == processID)
{
parentInfo.pid = pe32.th32ParentProcessID;
break;
}
} while (::Process32NextW(hSnapshot, &pe32));
// 親プロセスの名前を取得
if (parentInfo.pid != 0)
{
::Process32FirstW(hSnapshot, &pe32);
do
{
if (pe32.th32ProcessID == parentInfo.pid)
{
parentInfo.name = Unicode::FromWstring(pe32.szExeFile);
break;
}
} while (::Process32NextW(hSnapshot, &pe32));
}
}
::CloseHandle(hSnapshot);
return parentInfo;
}
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
MicrosecClock clock;
if (const Optional<ProcessInfo> parentInfo = GetParentProcess(::GetCurrentProcessId()))
{
clock.console();
Console << parentInfo->pid;
Console << parentInfo->name;
}
else
{
Console << U"Parent process not found";
}
while (System::Update())
{
}
}
実行中のファイルを含むフォルダの中に実行ファイルに対応する .pdb
ファイルが存在するか否かを調べることにより、中間ディレクトリで実行中か否かを判断すると効果的なのではないかと考えました。この方法についてご意見をお聞かせいただけますでしょうか
漏れていたケースをおおよそカバーできる、低コストで良い方法だと思います。 PDB を生成しないビルドオプションもあるので 100% にはなりませんが、採用してみたいと思います。 この先実装したらお知らせします。Rider で検証していただけると幸いです。
ありがとうございます!検証の件承知いたしました
v0.6 世代の Siv3D では JetBrains Rider を使用して開発およびエディタからのデバッグ実行が可能でした。しかし、現時点での v0.8 では
Failed to load a engine shader
というエラーダイアログが表示され、初期化に失敗します。詳しく調査したところ、初期化時の
SetWorkingDirectory
で Visual Studio 実行時かどうかを判定する条件分岐が、Rider実行時には適用されていないことが原因であることが分かりました。そのため、デバッグ時の実行ディレクトリがsiv8/WindowsDesktop/App/
ではなくsiv8/WindowsDesktop/Intermediate/Siv3D-Test/Debug/
になってしまいます。