Welcome, guest | Sign In | My Account | Store | Cart

Each file type has several commands saved in the registry and associated with the file type. These commands appear in the context menu for files of that file type. It seemed wasteful to replicate these commands with QEditor and Crimson Editor. DoCommand extracts the command from the registry, replaces macros and '%1' and '%*' strings and executes the command similar to the Do.py program.

Python, 202 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# ----------------------------------------------
# Name: Do
# Description: Expand and execute command
## D20H-23 Do command from Windows registry
#
# Author: Philip S. Rist
# Date: 10/12/2010
# Copyright 2010 by St. Thomas Software
# ----------------------------------------------
# This program is freeware.  It may be used
# for any moral purpose.  You use it at your
# own risk.  St. Thomas Software makes no
# guarantees to its fitness to do anything.
#
# If you feel you must pay for it. Please
# send one million dollars to
#
#     The International Rescue Committee
#     122 East 42nd Street
#     New York, N.Y.   10168-1289
#
# Ok, we are in a recession.  So, make it a half
# million.


from _winreg import *
import sys, os, os.path, getopt
import subprocess
import Do

def SubmitNow(pCommand):
    'Execute command'
    lCommand = '"' + pCommand + '"'
    #lCommand = 'c:\\bin\\messagebox.exe   ' + lCommand
    subprocess.Popen(lCommand, shell=True)

def GetExtensionInfo(pExtension):
    'Extract data saved in registry for specific extension'
    lHandle = OpenKey(HKEY_CLASSES_ROOT, pExtension)
    lSubKeys, lValueCount, lModified = QueryInfoKey(lHandle)
    lValues = {}
    for lCount in range(0, lValueCount):
        lName, lValue, lType = EnumValue(lHandle, lCount)
        if lName == '':
            lName = "File Type"
        lValues[lName] =lValue
        
    lKey = lValues['File Type']
    lDescription = QueryValue(HKEY_CLASSES_ROOT, lKey)
    lValues['Description'] = lDescription

    lKey += '\\Shell'
    lDefault = QueryValue(HKEY_CLASSES_ROOT, lKey)
    lValues['Default'] = lDefault    
    return lValues


def GetCommand(pFileType, pKey):
    'Retrieve text for selected command'
    lAbort = False
    try:
        lKey =  pFileType + "\\Shell\\" + pKey + "\\Command"
        lText = QueryValue(HKEY_CLASSES_ROOT, lKey)
    except:
        lText = ''
        lAbort = True
    return (lAbort, lText)


def BuildCommand(pExpandFile, pKey, pExtension, pArgs, pVerbose=False):
    '''
    The extension from pExpandFile is used to select the command associated with
    the command named in pKey for the file type associated with the given extension.

    pExpandFile - File to be processed
    pKey        - Command name
    pExtension  - Extension used to select command text
    pArgs       - Passed arguments

    Note: c:\messagebox.exe displays its command line in a popup window.
    '''
    if pVerbose:      # not currently used for anything
        lValues = GetExtensionInfo(pExtension)
    else:
        lValues = {}
    if len(pArgs) > 1:
        pArgs = pArgs[1:]
    else:
        pArgs = []
    lExpandFile = pExpandFile
    lKey = pKey
    lAbort = False
    
    lText = ''
    if len(lKey) > 0 and len(lExpandFile) > 0:
        lPos = lExpandFile.rfind('.')
        if lPos > 0:
            if pExtension == '':
                lExtension = lExpandFile[lPos:]
            else:
                lExtension = pExtension
            lFileType = QueryValue(HKEY_CLASSES_ROOT, lExtension)
            if len(lFileType) > 0:
                (lAbort, lText) = GetCommand(lFileType, lKey)
                if lAbort:
                    (lAbort, lText) = GetCommand('*', lKey)
            else:
                lAbort = True
                pass
        else:
            lAbort = True
            pass
    else:
        lAbort = True
        pass
        
    lArgs = ''
    if len(pArgs) > 0:
        lArgs = ' '.join(pArgs)
    if not lAbort:
        if lText.find("%") >= 0:
            lText = lText.replace("%1", str(lExpandFile))
            for lCount in range(0,len(pArgs)):
                lString = '%' + str(lCount+2)
                lText = lText.replace(lString, pArgs[lCount])
                lText = lText.replace("%*", lArgs)
        else:
            lText += " " + lExpandFile + " "+ lArgs
            
        if lText.find('{') >= 0:
            lText = Do.Expand(lText, lExpandFile)

    else:
        lText = ''
    return lText

def DoCommand(pExpandFile, pKey, pExtension, pArgs, pVerbose=False):
    lCommand = BuildCommand(pExpandFile, pKey, pExtension, pArgs, pVerbose)
    if len(lCommand) > 0:
        SubmitNow(lCommand)
    else:                              # requires a program that will display passed arguments
#        SubmitNow("c:\\bin\\messagebox.exe DoCommand: Execution aborted for " + pKey + 
#                          " on file " + pExpandFile )
        print 'Command not generated'

# DoCommand is designed to be executed from another program such as QEditor or Crimson Editor 
# which allow the user to define external commands.
#
# from QEditor:
#     Display References,c:\sys\python25\pythonw.exe  c:\bin\DoCommand.py  "{a}" RefList
#
#     This command will execute the RefList command associated with what ever file is being edited 
#     passing that file.  Most useful with a program such as Crimson Editor which provide for only
#     a limited number of user defined commands.

#sys.argv.extend(['-x', '.txt', 'c:\\source\\python\\Projects\\Program Execution\\docommand.py', 
#                'Open', 'First', '{p}' ])
#     uses Open command for .txt files to open Python source file

if __name__ == '__main__':
    lSys = len(sys.argv)
    if lSys > 1:
        (mOptions, mArgs) = getopt.getopt(sys.argv[1:], 'd:e:vx:')
        
        mFileName = mExpandFile = mArgs[0]  # 1st Path to file
        
        if len(mArgs) > 1:                  # 2nd command name
            mCommand = mArgs[1]             # 3rd on command arguments
            mArgs = mArgs[1:]
        else:
            mCommand = "Open"
        
        lPos = mExpandFile.rfind('.')
        if lPos >= 0:
            mExtension = mExpandFile[lPos:]
        else:
            mExtension = ''

        mVerbose = False
        
        for (mKey, mValue) in mOptions:  
            if mKey == '-d':                 # Set current directory
                if mValue.find('}'):
                    mValue = Do.Expand(mValue, mFileName)
                os.chdir(mValue)
                
            elif mKey == '-e':               # Set environment variable
                setenviron(mValue, mFileName)

            elif mKey == '-v':               # Run in verbose mode
                mVervose = True
                
            elif mKey == '-x':               # override extension where command
                mExtension = mValue          # is extracted

        if mExtension == '':
            mExtension = 'txt'
                    
        DoCommand(mExpandFile, mCommand, mExtension, mArgs, pVerbose=mVerbose)
    else:
        #SubmitNow("c:\\bin\\messagebox.exe DoCommand.py requires a file name and a command name")
        print "DoCommand.py requires a file name and a command name"

This program has been tested under Win32 XP with Active State 2.5 and 2.7. I was trying to provide a way to use commands located in the Win32 registry from editors/ides which allow modification of their menus or from other registry entries or batch files without duplication.