Sei que essa pergunta já foi feita antes, mas ainda não vi uma resposta satisfatória, ou um "não, isso não pode ser feito" definitivo, então vou perguntar novamente!
Tudo o que quero fazer é obter o caminho para o executável em execução no momento, seja como um caminho absoluto ou relativo ao local de onde o executável é chamado, de forma independente da plataforma. Eu pensei que boost :: filesystem :: initial_path fosse a resposta para meus problemas, mas isso parece lidar apenas com a parte 'independente de plataforma' da questão - ele ainda retorna o caminho de onde o aplicativo foi chamado.
Para um pouco de fundo, este é um jogo usando Ogre, que estou tentando criar o perfil usando Very Sleepy, que executa o executável alvo de seu próprio diretório, então é claro que ao carregar o jogo não encontra arquivos de configuração etc. e trava imediatamente . Quero ser capaz de passar um caminho absoluto para os arquivos de configuração, que sei que sempre viverão junto com o executável. O mesmo se aplica à depuração no Visual Studio - gostaria de poder executar $ (TargetPath) sem precisar definir o diretório de trabalho.
fonte
Respostas:
Não existe uma forma de plataforma cruzada que eu conheça.
Para Linux: readlink / proc / self / exe
Windows: GetModuleFileName
fonte
A função boost :: dll :: program_location é um dos melhores métodos de plataforma cruzada para obter o caminho do executável em execução que eu conheço. A biblioteca DLL foi adicionada ao Boost na versão 1.61.0.
O seguinte é minha solução. Eu testei no Windows, Mac OS X, Solaris, Free BSD e GNU / Linux.
Requer Boost 1.55.0 ou superior. Ele usa a biblioteca Boost.Filesystem diretamente eo Boost.Locale biblioteca e Boost.System indiretamente.
src / executable_path.cpp
src / detail / executable_path_internals.cpp
include / boost / executable_path.hpp
include / boost / detail / executable_path_internals.hpp
Eu tenho um projeto completo, incluindo um aplicativo de teste e arquivos de compilação CMake disponíveis em SnKOpen - / cpp / executable_path / trunk . Esta versão é mais completa do que a versão que forneci aqui. Também é compatível com mais plataformas.
Testei o aplicativo em todos os sistemas operacionais com suporte nos quatro cenários a seguir.
Em todos os quatro cenários, as funções executable_path e executable_path_fallback funcionam e retornam os mesmos resultados.
Notas
Esta é uma resposta atualizada a esta pergunta. Atualizei a resposta para levar em consideração os comentários e sugestões dos usuários. Também adicionei um link para um projeto em meu repositório SVN.
fonte
argv[0]
também pode ser apenas um nome executável, caso em que seria necessário procurá-lo nosPATH
sistemas * nix.Desta forma, usa boost + argv. Você mencionou que pode não ser uma plataforma cruzada porque pode ou não incluir o nome do executável. Bem, o código a seguir deve contornar isso.
O código a seguir obtém o diretório de trabalho atual que pode fazer o que você precisa
Observação Acabei de perceber que
basename(
) foi descontinuado, então tive que mudar para.stem()
fonte
.parent_path()
, não.stem()
, não?@Claudiu
disse, acho que deveria ser.parent_path()
.Não tenho certeza sobre o Linux, mas tente isso para Windows:
fonte
WCHAR ownPth..
, enrolado#ifdef UNICODE
em caso de compilar com suporte a Unicode. Caso contrário, use o código fornecido.HMODULE hModule = GetModuleHandle(NULL);
Para Windows:
GetModuleFileName
- retorna o caminho exe + nome do arquivo exePara remover o nome do arquivo
PathRemoveFileSpec
fonte
This function is deprecated. We recommend the use of the PathCchRemoveFileSpec function in its place
.C ++ 17, windows, unicode, usando sistema de arquivos new api:
Suspeito que esta solução deve ser portátil, mas não sei como unicode é implementado em outros sistemas operacionais.
weakly_canonical é necessário apenas se você usar como referências de pasta superior do diretório de saída ('..') para simplificar o caminho. Se você não usar, remova-o.
Se você estiver operando a partir de uma biblioteca de vínculo dinâmico (.dll /.so), pode não ter argv, então você pode considerar a seguinte solução:
aplicação.h:
application.cpp:
fonte
QT fornece isso com abstração de sistema operacional como QCoreApplication :: applicationDirPath ()
fonte
QCoreApplication::applicationDirPath: Please instantiate the QApplication object first
. Alguma ideia de como resolver isso?QCoreApplication
semelhanteQApplication application(argc, argv);
(faça isso em seumain(argc, argv)
e certifique-se de não modificar oargc/argv
, pois eles precisam permanecer válidos durante a vida útil do QCoreApplication (verifique a documentação )Esta é uma maneira específica do Windows, mas é pelo menos metade de sua resposta.
GetThisPath.h
GetThisPath.cpp
mainProgram.cpp
Eu sugeriria o uso de detecção de plataforma como diretivas de pré-processador para alterar a implementação de uma função de wrapper que chama
GetThisPath
cada plataforma.fonte
Usando args [0] e procurando por '/' (ou '\\'):
EDITADO: Se '/' não existe, pos == - 1 então o resultado está correto.
fonte
args[0]
pode não ser realmente um caminho.args[0]
não ser necessariamente o caminho executável que me incomoda. Obrigado por corrigir sua resposta para o Windows :)Para Windows, você pode usar GetModuleFilename ().
Para Linux, veja o
espelho BinReloc (URL antigo, extinto)do BinReloc nos repositórios GitHub do datenwolf .fonte
O seguinte funciona como uma solução rápida e suja, mas observe que está longe de ser à prova de falhas:
fonte
Caso você precise lidar com caminhos Unicode para Windows:
fonte
Para Windows, você tem o problema de como remover o executável do resultado de
GetModuleFileName()
. A chamada de API do WindowsPathRemoveFileSpec()
que Nate usou para esse propósito em sua resposta mudou entre o Windows 8 e seus predecessores. Então, como permanecer compatível com ambos e seguro? Felizmente, existe o C ++ 17 (ou Boost, se você estiver usando um compilador mais antigo). Eu faço isso:fonte
Como outros mencionaram,
argv[0]
é uma boa solução, desde que a plataforma realmente passe pelo caminho do executável, o que certamente não é menos provável do que o sistema operacional sendo Windows (onde o WinAPI pode ajudar a encontrar o caminho do executável). Se você quiser retirar a string para incluir apenas o caminho para o diretório onde o executável reside, usar esse caminho para encontrar outros arquivos de aplicativo (como ativos de jogo se o seu programa for um jogo) é perfeitamente adequado, já que abrir arquivos é relativo a o diretório de trabalho ou, se fornecido, a raiz.fonte
Isso é o que eu terminei
O arquivo de cabeçalho tem a seguinte aparência:
Implementação
fonte
A biblioteca SDL2 ( https://www.libsdl.org/ ) tem duas funções implementadas em um amplo espectro de plataformas:
Então, se você não quer reinventar a roda ... infelizmente, significa incluir a biblioteca inteira, embora ela tenha uma licença bastante permissiva e também se possa copiar o código. Além disso, oferece muitas outras funcionalidades de plataforma cruzada.
fonte
Esta é provavelmente a maneira mais natural de fazer isso, enquanto cobre a maioria das principais plataformas de desktop. Não tenho certeza, mas acredito que deve funcionar com todos os BSDs, não apenas com o FreeBSD, se você alterar a verificação da macro da plataforma para cobrir todos eles. Se eu conseguir instalar o Solaris, com certeza adicionarei essa plataforma à lista de suporte.
Possui suporte total a UTF-8 no Windows, o que nem todos se importam o suficiente para ir tão longe.
procinfo / win32 / procinfo.cpp
procinfo / macosx / procinfo.cpp
procinfo / linux / procinfo.cpp
procinfo / freebsd / procinfo.cpp
procinfo / procinfo.cpp
procinfo / procinfo.h
Isso permite obter o caminho completo para o executável de praticamente qualquer id de processo, exceto no Windows, existem alguns processos com atributos de segurança que simplesmente não permitem isso, então wysiwyg, esta solução não é perfeita.
Para responder ao que a pergunta estava perguntando com mais precisão, você pode fazer o seguinte:
procinfo.cpp
Crie a estrutura de arquivo acima com este comando:
procinfo.sh
Para baixar uma cópia dos arquivos listados acima:
Para mais vantagens relacionadas ao processo de plataforma cruzada:
https://github.com/time-killer-games/enigma-dev
Consulte o leiame para obter uma lista da maioria das funções incluídas.
fonte
Se estiver usando C ++ 17, pode-se fazer o seguinte para obter o caminho para o executável.
A resposta acima foi testada no Debian 10 usando G ++ 9.3.0
fonte
A partir de C ++ 17:
Certifique-se de incluir o sistema de arquivos std.
e agora você pode fazer isso.
boost filesystem tornou-se parte da biblioteca padrão.
se você não conseguir encontrar, tente procurar em:
fonte
Esta foi a minha solução no Windows. É chamado assim:
Onde 64 é o tamanho mínimo que você acha que será o caminho. GetPathOfEXE chama a si mesmo recursivamente, dobrando o tamanho do buffer a cada vez, até que obtenha um buffer grande o suficiente para obter o caminho inteiro sem truncamento.
fonte
new
e o (errado)delete
? Se você tivesse usado umstd::vector
, seu código não teria exibido um comportamento indefinido.GetModuleFileNameW
não define o último código de erro em caso de sucesso. Esse código é quebrado de muitas maneiras. Não use se acontecer de você tropeçar nisso.fonte
PathRemoveFileSpec()
funções relacionadas.no Unix (incluindo Linux) tente 'which', no Windows tente 'where'.
fonte
Este método funciona para Windows e Linux:
fonte