mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
panda3dw.exe, and file-associations for windows
This commit is contained in:
parent
6bd5ec1c5a
commit
216211343f
190
direct/src/plugin_installer/FileAssociation.nsh
Executable file
190
direct/src/plugin_installer/FileAssociation.nsh
Executable file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
_____________________________________________________________________________
|
||||
|
||||
File Association
|
||||
_____________________________________________________________________________
|
||||
|
||||
Based on code taken from http://nsis.sourceforge.net/File_Association
|
||||
|
||||
Usage in script:
|
||||
1. !include "FileAssociation.nsh"
|
||||
2. [Section|Function]
|
||||
${FileAssociationFunction} "Param1" "Param2" "..." $var
|
||||
[SectionEnd|FunctionEnd]
|
||||
|
||||
FileAssociationFunction=[RegisterExtension|UnRegisterExtension]
|
||||
|
||||
_____________________________________________________________________________
|
||||
|
||||
${RegisterExtension} "[executable]" "[extension]" "[description]"
|
||||
|
||||
"[executable]" ; executable which opens the file format
|
||||
;
|
||||
"[extension]" ; extension, which represents the file format to open
|
||||
;
|
||||
"[description]" ; description for the extension. This will be display in Windows Explorer.
|
||||
;
|
||||
|
||||
|
||||
${UnRegisterExtension} "[extension]" "[description]"
|
||||
|
||||
"[extension]" ; extension, which represents the file format to open
|
||||
;
|
||||
"[description]" ; description for the extension. This will be display in Windows Explorer.
|
||||
;
|
||||
|
||||
_____________________________________________________________________________
|
||||
|
||||
Macros
|
||||
_____________________________________________________________________________
|
||||
|
||||
Change log window verbosity (default: 3=no script)
|
||||
|
||||
Example:
|
||||
!include "FileAssociation.nsh"
|
||||
!insertmacro RegisterExtension
|
||||
${FileAssociation_VERBOSE} 4 # all verbosity
|
||||
!insertmacro UnRegisterExtension
|
||||
${FileAssociation_VERBOSE} 3 # no script
|
||||
*/
|
||||
|
||||
|
||||
!ifndef FileAssociation_INCLUDED
|
||||
!define FileAssociation_INCLUDED
|
||||
|
||||
!include Util.nsh
|
||||
|
||||
!verbose push
|
||||
!verbose 3
|
||||
!ifndef _FileAssociation_VERBOSE
|
||||
!define _FileAssociation_VERBOSE 3
|
||||
!endif
|
||||
!verbose ${_FileAssociation_VERBOSE}
|
||||
!define FileAssociation_VERBOSE `!insertmacro FileAssociation_VERBOSE`
|
||||
!verbose pop
|
||||
|
||||
!macro FileAssociation_VERBOSE _VERBOSE
|
||||
!verbose push
|
||||
!verbose 3
|
||||
!undef _FileAssociation_VERBOSE
|
||||
!define _FileAssociation_VERBOSE ${_VERBOSE}
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
!macro RegisterExtensionCall _EXECUTABLE _EXTENSION _DESCRIPTION
|
||||
!verbose push
|
||||
!verbose ${_FileAssociation_VERBOSE}
|
||||
Push `${_DESCRIPTION}`
|
||||
Push `${_EXTENSION}`
|
||||
Push `${_EXECUTABLE}`
|
||||
${CallArtificialFunction} RegisterExtension_
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
!macro UnRegisterExtensionCall _EXTENSION _DESCRIPTION
|
||||
!verbose push
|
||||
!verbose ${_FileAssociation_VERBOSE}
|
||||
Push `${_EXTENSION}`
|
||||
Push `${_DESCRIPTION}`
|
||||
${CallArtificialFunction} UnRegisterExtension_
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
!define RegisterExtension `!insertmacro RegisterExtensionCall`
|
||||
!define un.RegisterExtension `!insertmacro RegisterExtensionCall`
|
||||
|
||||
!macro RegisterExtension
|
||||
!macroend
|
||||
|
||||
!macro un.RegisterExtension
|
||||
!macroend
|
||||
|
||||
!macro RegisterExtension_
|
||||
!verbose push
|
||||
!verbose ${_FileAssociation_VERBOSE}
|
||||
|
||||
Exch $R2 ;exe
|
||||
Exch
|
||||
Exch $R1 ;ext
|
||||
Exch
|
||||
Exch 2
|
||||
Exch $R0 ;desc
|
||||
Exch 2
|
||||
Push $0
|
||||
Push $1
|
||||
|
||||
ReadRegStr $1 HKCR $R1 "" ; read current file association
|
||||
StrCmp "$1" "" NoBackup ; is it empty
|
||||
StrCmp "$1" "$R0" NoBackup ; is it our own
|
||||
WriteRegStr HKCR $R1 "backup_val" "$1" ; backup current value
|
||||
NoBackup:
|
||||
WriteRegStr HKCR $R1 "" "$R0" ; set our file association
|
||||
|
||||
ReadRegStr $0 HKCR $R0 ""
|
||||
StrCmp $0 "" 0 Skip
|
||||
WriteRegStr HKCR "$R0" "" "$R0"
|
||||
WriteRegStr HKCR "$R0\shell" "" "open"
|
||||
WriteRegStr HKCR "$R0\DefaultIcon" "" "$R2,0"
|
||||
Skip:
|
||||
WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"'
|
||||
WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0"
|
||||
WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"'
|
||||
|
||||
Pop $1
|
||||
Pop $0
|
||||
Pop $R2
|
||||
Pop $R1
|
||||
Pop $R0
|
||||
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
!define UnRegisterExtension `!insertmacro UnRegisterExtensionCall`
|
||||
!define un.UnRegisterExtension `!insertmacro UnRegisterExtensionCall`
|
||||
|
||||
!macro UnRegisterExtension
|
||||
!macroend
|
||||
|
||||
!macro un.UnRegisterExtension
|
||||
!macroend
|
||||
|
||||
!macro UnRegisterExtension_
|
||||
!verbose push
|
||||
!verbose ${_FileAssociation_VERBOSE}
|
||||
|
||||
Exch $R1 ;desc
|
||||
Exch
|
||||
Exch $R0 ;ext
|
||||
Exch
|
||||
Push $0
|
||||
Push $1
|
||||
|
||||
ReadRegStr $1 HKCR $R0 ""
|
||||
StrCmp $1 $R1 0 NoOwn ; only do this if we own it
|
||||
ReadRegStr $1 HKCR $R0 "backup_val"
|
||||
StrCmp $1 "" 0 Restore ; if backup="" then delete the whole key
|
||||
DeleteRegKey HKCR $R0
|
||||
Goto NoOwn
|
||||
|
||||
Restore:
|
||||
WriteRegStr HKCR $R0 "" $1
|
||||
DeleteRegValue HKCR $R0 "backup_val"
|
||||
DeleteRegKey HKCR $R1 ;Delete key with association name settings
|
||||
|
||||
NoOwn:
|
||||
|
||||
Pop $1
|
||||
Pop $0
|
||||
Pop $R1
|
||||
Pop $R0
|
||||
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
!endif # !FileAssociation_INCLUDED
|
@ -125,21 +125,66 @@ def parseDependenciesWindows(tempFile):
|
||||
# At least we got some data.
|
||||
return filenames
|
||||
|
||||
def addDependencies(path, pathname, file, pluginDependencies, dependentFiles):
|
||||
""" Checks the named file for DLL dependencies, and adds any
|
||||
appropriate dependencies found into pluginDependencies and
|
||||
dependentFiles. """
|
||||
|
||||
tempFile = Filename.temporary('', 'p3d_', '.txt')
|
||||
command = 'dumpbin /dependents "%s" >"%s"' % (
|
||||
pathname.toOsSpecific(),
|
||||
tempFile.toOsSpecific())
|
||||
try:
|
||||
os.system(command)
|
||||
except:
|
||||
pass
|
||||
filenames = None
|
||||
|
||||
if tempFile.exists():
|
||||
filenames = parseDependenciesWindows(tempFile)
|
||||
tempFile.unlink()
|
||||
if filenames is None:
|
||||
sys.exit("Unable to determine dependencies from %s" % (pathname))
|
||||
|
||||
# Look for MSVC[RP]*.dll, and MFC*.dll. These dependent files
|
||||
# have to be included too. Also, any Panda-based libraries, or
|
||||
# the Python DLL, should be included, in case panda3d.exe wasn't
|
||||
# built static. The Panda-based libraries begin with "lib" and
|
||||
# are all lowercase.
|
||||
for dfile in filenames:
|
||||
dfilelower = dfile.lower()
|
||||
if dfilelower not in dependentFiles:
|
||||
if dfilelower.startswith('msvc') or \
|
||||
dfilelower.startswith('mfc') or \
|
||||
(dfile.startswith('lib') and dfile == dfilelower) or \
|
||||
dfilelower.startswith('python'):
|
||||
pathname = path.findFile(dfile)
|
||||
if not pathname:
|
||||
sys.exit("Couldn't find %s." % (dfile))
|
||||
dependentFiles[dfilelower] = pathname.toOsSpecific()
|
||||
|
||||
# Also recurse.
|
||||
addDependencies(path, pathname, file, pluginDependencies, dependentFiles)
|
||||
|
||||
if dfilelower in dependentFiles:
|
||||
pluginDependencies[file].append(dfilelower)
|
||||
|
||||
def makeInstaller():
|
||||
# Locate the plugin(s).
|
||||
pluginFiles = {}
|
||||
pluginDependencies = {}
|
||||
dependentFiles = {}
|
||||
|
||||
# These are the three primary files that make up the
|
||||
# These are the four primary files that make up the
|
||||
# plugin/runtime.
|
||||
ocx = 'p3dactivex.ocx'
|
||||
npapi = 'nppanda3d.dll'
|
||||
panda3d = 'panda3d.exe'
|
||||
panda3dw = 'panda3dw.exe'
|
||||
|
||||
path = DSearchPath()
|
||||
path.appendPath(os.environ['PATH'])
|
||||
for file in [ocx, npapi, panda3d]:
|
||||
for file in [ocx, npapi, panda3d, panda3dw]:
|
||||
pathname = path.findFile(file)
|
||||
if not pathname:
|
||||
sys.exit("Couldn't find %s." % (file))
|
||||
@ -148,32 +193,7 @@ def makeInstaller():
|
||||
pluginDependencies[file] = []
|
||||
|
||||
# Also look for the dll's that these plugins reference.
|
||||
tempFile = Filename.temporary('', 'p3d_', '.txt')
|
||||
command = 'dumpbin /dependents "%s" >"%s"' % (
|
||||
pathname.toOsSpecific(),
|
||||
tempFile.toOsSpecific())
|
||||
try:
|
||||
os.system(command)
|
||||
except:
|
||||
pass
|
||||
filenames = None
|
||||
|
||||
if tempFile.exists():
|
||||
filenames = parseDependenciesWindows(tempFile)
|
||||
tempFile.unlink()
|
||||
if filenames is None:
|
||||
sys.exit("Unable to determine dependencies from %s" % (pathname))
|
||||
|
||||
# Look for MSVC[RP]*.dll, and MFC*.dll. These dependent files
|
||||
# have to be included too.
|
||||
for dfile in filenames:
|
||||
dfile = dfile.lower()
|
||||
if dfile.startswith('msvc') or dfile.startswith('mfc'):
|
||||
pathname = path.findFile(dfile)
|
||||
if not pathname:
|
||||
sys.exit("Couldn't find %s." % (dfile))
|
||||
pluginDependencies[file].append(dfile)
|
||||
dependentFiles[dfile] = pathname.toOsSpecific()
|
||||
addDependencies(path, pathname, file, pluginDependencies, dependentFiles)
|
||||
|
||||
welcomeBitmap = None
|
||||
if options.welcome_image:
|
||||
@ -216,6 +236,8 @@ def makeInstaller():
|
||||
CMD += '/DNPAPI_PATH="' + pluginFiles[npapi] + '" '
|
||||
CMD += '/DPANDA3D="' + panda3d + '" '
|
||||
CMD += '/DPANDA3D_PATH="' + pluginFiles[panda3d] + '" '
|
||||
CMD += '/DPANDA3DW="' + panda3dw + '" '
|
||||
CMD += '/DPANDA3DW_PATH="' + pluginFiles[panda3dw] + '" '
|
||||
|
||||
dependencies = dependentFiles.items()
|
||||
for i in range(len(dependencies)):
|
||||
|
@ -1,6 +1,7 @@
|
||||
!include "MUI.nsh"
|
||||
!include LogicLib.nsh
|
||||
!include FileFunc.nsh
|
||||
!include FileAssociation.nsh
|
||||
|
||||
; Several variables are assumed to be pre-defined by the caller. See
|
||||
; make_installer.py in this directory.
|
||||
@ -73,6 +74,7 @@ Section "MainSection" SEC01
|
||||
File "${OCX_PATH}"
|
||||
File "${NPAPI_PATH}"
|
||||
File "${PANDA3D_PATH}"
|
||||
File "${PANDA3DW_PATH}"
|
||||
|
||||
; Auto-detected dependencies on the above executables. Python
|
||||
; computes these values for us.
|
||||
@ -91,7 +93,15 @@ Section "MainSection" SEC01
|
||||
!ifdef DEP4P
|
||||
File "${DEP4P}"
|
||||
!endif
|
||||
!ifdef DEP5P
|
||||
File "${DEP5P}"
|
||||
!endif
|
||||
!ifdef DEP6P
|
||||
File "${DEP6P}"
|
||||
!endif
|
||||
|
||||
${registerExtension} "$INSTDIR\${PANDA3DW}" ".p3d" "Panda3D applet"
|
||||
|
||||
!ifdef ADD_START_MENU
|
||||
; Start->Programs links
|
||||
CreateDirectory "$SMPROGRAMS\${PROG_GROUPNAME}"
|
||||
@ -166,6 +176,12 @@ Mozilla-Install-Loop:
|
||||
!endif
|
||||
!ifdef NPAPI_DEP4
|
||||
CopyFiles $INSTDIR\${NPAPI_DEP4} "$2"
|
||||
!endif
|
||||
!ifdef NPAPI_DEP5
|
||||
CopyFiles $INSTDIR\${NPAPI_DEP5} "$2"
|
||||
!endif
|
||||
!ifdef NPAPI_DEP6
|
||||
CopyFiles $INSTDIR\${NPAPI_DEP6} "$2"
|
||||
!endif
|
||||
${EndIf}
|
||||
|
||||
@ -183,6 +199,7 @@ Section Uninstall
|
||||
Delete "$INSTDIR\${OCX}"
|
||||
Delete "$INSTDIR\${NPAPI}"
|
||||
Delete "$INSTDIR\${PANDA3D}"
|
||||
Delete "$INSTDIR\${PANDA3DW}"
|
||||
!ifdef DEP0
|
||||
Delete "$INSTDIR\${DEP0}"
|
||||
!endif
|
||||
@ -198,6 +215,12 @@ Section Uninstall
|
||||
!ifdef DEP4
|
||||
Delete "$INSTDIR\${DEP4}"
|
||||
!endif
|
||||
!ifdef DEP5
|
||||
Delete "$INSTDIR\${DEP5}"
|
||||
!endif
|
||||
!ifdef DEP6
|
||||
Delete "$INSTDIR\${DEP6}"
|
||||
!endif
|
||||
|
||||
StrCpy $1 "0"
|
||||
Mozilla-Uninstall-Loop:
|
||||
@ -213,7 +236,7 @@ Mozilla-Uninstall-Loop:
|
||||
goto Mozilla-Uninstall-Loop
|
||||
Mozilla-Uninstall-End:
|
||||
|
||||
ReadRegDWORD $0 HKLM SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System EnableLUA
|
||||
${unregisterExtension} ".p3d" "Panda3D applet"
|
||||
|
||||
# Remove the user's "Panda3D" directory, where all of the downloaded
|
||||
# contents are installed. Too bad we can't do this for every system
|
||||
|
@ -26,3 +26,29 @@
|
||||
#endif
|
||||
|
||||
#end bin_target
|
||||
|
||||
#begin bin_target
|
||||
// On Windows, we also need to build panda3dw.exe, the non-console
|
||||
// version of panda3d.exe.
|
||||
|
||||
#define BUILD_TARGET $[WINDOWS_PLATFORM]
|
||||
#define USE_PACKAGES openssl zlib
|
||||
#define TARGET panda3dw
|
||||
#define EXTRA_CDEFS NON_CONSOLE
|
||||
|
||||
#define LOCAL_LIBS plugin_common
|
||||
|
||||
#define OTHER_LIBS \
|
||||
prc:c dtoolutil:c dtoolbase:c dtool:m \
|
||||
interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
express:c downloader:c pandaexpress:m \
|
||||
pystub
|
||||
|
||||
#define OSX_SYS_FRAMEWORKS Foundation AppKit Carbon
|
||||
|
||||
#define SOURCES \
|
||||
panda3d.cxx panda3d.h panda3d.I
|
||||
|
||||
#define WIN_SYS_LIBS user32.lib gdi32.lib shell32.lib ole32.lib
|
||||
|
||||
#end bin_target
|
||||
|
@ -52,6 +52,12 @@ Panda3D() {
|
||||
_root_dir = find_root_dir();
|
||||
_reporting_download = false;
|
||||
_enable_security = false;
|
||||
|
||||
#ifdef NON_CONSOLE
|
||||
// For the desktop version of this program, let's always assume -S
|
||||
// is in effect.
|
||||
_enable_security = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1126,8 +1132,77 @@ run() {
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(NON_CONSOLE)
|
||||
// On Windows, we may need to build panda3dw.exe, a non-console
|
||||
// version of this program.
|
||||
|
||||
// Returns a newly-allocated string representing the quoted argument
|
||||
// beginning at p. Advances p to the first character following the
|
||||
// close quote.
|
||||
static char *
|
||||
parse_quoted_arg(char *&p) {
|
||||
char quote = *p;
|
||||
++p;
|
||||
string result;
|
||||
|
||||
while (*p != '\0' && *p != quote) {
|
||||
// TODO: handle escape characters? Not sure if we need to.
|
||||
result += *p;
|
||||
++p;
|
||||
}
|
||||
if (*p == quote) {
|
||||
++p;
|
||||
}
|
||||
return strdup(result.c_str());
|
||||
}
|
||||
|
||||
// Returns a newly-allocated string representing the unquoted argument
|
||||
// beginning at p. Advances p to the first whitespace following the
|
||||
// argument.
|
||||
static char *
|
||||
parse_unquoted_arg(char *&p) {
|
||||
string result;
|
||||
while (*p != '\0' && !isspace(*p)) {
|
||||
result += *p;
|
||||
++p;
|
||||
}
|
||||
return strdup(result.c_str());
|
||||
}
|
||||
|
||||
WINAPI
|
||||
WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
|
||||
char *command_line = GetCommandLine();
|
||||
|
||||
vector<char *> argv;
|
||||
|
||||
char *p = command_line;
|
||||
while (*p != '\0') {
|
||||
if (*p == '"') {
|
||||
char *arg = parse_quoted_arg(p);
|
||||
argv.push_back(arg);
|
||||
} else {
|
||||
char *arg = parse_unquoted_arg(p);
|
||||
argv.push_back(arg);
|
||||
}
|
||||
|
||||
// Skip whitespace.
|
||||
while (*p != '\0' && isspace(*p)) {
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!argv.empty());
|
||||
|
||||
Panda3D program;
|
||||
return program.run(argv.size(), &argv[0]);
|
||||
}
|
||||
|
||||
#else // NON_CONSOLE
|
||||
|
||||
// The normal, "console" program.
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
Panda3D program;
|
||||
return program.run(argc, argv);
|
||||
}
|
||||
#endif // NON_CONSOLE
|
||||
|
Loading…
x
Reference in New Issue
Block a user