vbs syntax error: 800A03EE ')' expected - visual-studio

I try to execute this in a file called 'addcurrentkey.vbs'
But it says ')' is expected in row 1. Character 38.
I tried this tutorial: http://www.codeproject.com/Articles/16569/Autorun-Applications
Why can't I execute a .vbs file?
Private Sub AddCurrentKey(ByVal name As String, ByVal path As String)
Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run", True)
key.SetValue(name, path)
End Sub

The code you posted is probably written in VB.net (or perhaps VBA). You are tying to run the code as VBScript, which does not support typed parameters and variables. It also doesn't provide the registry object you're trying to use. Change the procedure from this:
Private Sub AddCurrentKey(ByVal name As String, ByVal path As String)
Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run", True)
key.SetValue(name, path)
End Sub
to this:
Private Sub AddCurrentKey(ByVal name, ByVal path)
Dim key : key = "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"
CreateObject("WScript.Shell").RegWrite key & "\" & name, path
End Sub
and the problem will disappear.

VBScript still uses the "old" Visual Basic syntax. Which distinguishes between function calls used in expressions and procedure calls that are statements. You use (parentheses) in an expression but not in a statement. Fix:
key.SetValue name, path
Or if you prefer:
Call key.SetValue(name, path)
The error message is hard to interpret because the script interpreter thinks that you are trying to write this:
key.SetValue (name), path
Which means something completely different. VBScript passes arguments ByRef. The extra parentheses around name turns it into an expression that creates a copy of the variable. It can be modified by the SetValue procedure without it affecting the name variable. Not what it actually does nor what you intended.

Related

VB6: ShellExecute an EXE inside AppData

I have the following sub:
Public Sub ShellApp(URL As String)
Dim vResult As Long
vResult = ShellExecute(0, "open", URL, vbNullString, vbNullString, vbMinimizedFocus)
End If
End Sub
This is on a layer that cannot be changed due to several functionality needed on that sub.
Now, on our Main() sub for example, we check a list of added plugins saved in a text file beside the EXE, and call the above Sub in for loop with the path of the plugins to run them. So if I have 3 plugins as below in the text file:
C:\App1.EXE
C:\App2.EXE
C:\Users\AhmadMusa\AppData\Roaming\App3.exe
First two apps will run fine on all PCs (Static path), but third app will not work on any PC except mine which is not ok... Note that App3 always installed on AppData on any PC, so how to dynamically access it to run the app from any PC without adjustments on the sub.
What will be the path placed in the text file for third app so it can work on all PCs?
I tried (AppData\Roaming\App3.exe) but it does not work... I found on a thread (http://www.vbforums.com/showthread.php?529776-RESOLVED-Open-a-folder-in-AppData) that I can call something like (shell:AppData\Roaming\App3.exe) it did not work to run the App3.exe, but if I call (shell:AppData\Roaming) it will open the Roaming folder very well. But cannot run the EXE.
Any ideas ?
Thanks.
I believe that there is no way to solve the problem without altering the original procedure "ShellApp".
in case you change your mind, i think this post may come in help (with some tweekings)
Public Sub ShellApp(URL As String)
Dim vResult As Long
'vResult = ShellExecute(0, vbNullString, URL, vbNullString, vbNullString, vbNormalFocus)
vResult = ShellExecute(0, vbNullString, "cmd.exe", "/k """"" & URL & """""", vbNullString, vbNormalFocus)
End Sub
Private Sub Command1_Click()
ShellApp "%appdata%\PROGRAME.exe"
End Sub
this because only "cmd.exe" and ofcourse batch scripts are able to expend variables that are enclosed with percent character "%"
To close the console as soon as it starts change the parameter "/k" to "/c",
sub test()
dim tmp as string
tmp = environ("AppData ") & "\calc.exe"
call ShellExecute(..., tmp, ...)
end sub
fill the other arguments (...) the way you see it right
You need to expand the Environment variable (this is what the %...% does):
Debug.Print Environ("APPDATA") ' will print the expanded %appdata%
So, in your text file you should put:
%APPDATA%\App3.exe
How to expand the path? You can loop over the environment variables provided by the VB Environ function and do a string replace by yourself (the VB way) or you can profit from the ExpandEnvironmentStrings function (the Win32 API way).
Below a snippet using this second option:
Private Declare Function ExpandEnvironmentStrings Lib "kernel32.dll" _
Alias "ExpandEnvironmentStringsA" ( _
ByVal lpSrc As String, _
ByVal lpDst As String, _
ByVal nSize As Long) As Long
Public Function ExpandEnvironString(ByVal URL As String) As String
Dim buf As String, bufSize As Long
bufSize = ExpandEnvironmentStrings(URL, ByVal 0&, 0&)
buf = String(bufSize + 1, vbNullChar)
bufSize = ExpandEnvironmentStrings(URL, buf, Len(buf))
ExpandEnvironString = Left$(buf, InStr(1, buf, vbNullChar) - 1)
End Function
Before you call ShellApp(URL As String) you should expand the path:
URL = ExpandEnvironString(URL)
ShellExecute will receive the expanded path: C:\Users\AhmadMusa\AppData\Roaming\App3.exe
This is a non-breaking change, because if your initial default setting will be later changed to a custom fixed path, the ExpandEnvironmentStrings function will simply ignore it.
Example:
ExpandEnvironString("C:\App1.EXE ") will return C:\App1.EXE
More info:
you can get all your environment variables with following procedure:
Private Sub EnvironmentEntries()
Dim Entry As String, i As Long
i = 1
Do
Entry = Environ(i)
i = i + 1
If Entry = "" Then Exit Do
Debug.Print Entry
Loop
End Sub
... and check some additional info here:
Why are there directories called Local, LocalLow, and Roaming under \Users\?

vb6, variable not defined for Label using Module

Sorry to ask such a dumb question.. but for the life of me i cant get it.. i have searched EVERYWHERE... This is a Re-Creation of my code that gives the same error. This is the most basic example i could re-create.
I dont understand why i have to declare a Label ?? (or an object)
What I am trying to accomplish is use my main form to call all the modules.
This is the FORM
'frmMain.frm
Option Explicit
Public Sub btnOpen_Click()
GetNum
End Sub
This is the MODULE
'modGet.bas
Option Explicit
Public Sub GetNum()
Dim a As String
Dim b As String
a = "hello"
b = "world"
-> Label1.Caption = a 'ERROR, Compile Error, Variable not Defined. (vb6)
Label2.Caption = b
End Sub
YES, i have a form, with a Button named 'btnOpen', i have 2 Labels named 'Label1' & 'Label2'
If i ADD..
Dim Label1 As Object 'in MODULE
i get a different error..
ERROR '91' Object Variable or With block variable not set
IF I put everything in 1 FORM, it works..(but i want to use separate modules)
I Commented out 'OPTION EXPLICIT' ... same error.
In another Test, i got the error for a TextBox..
TextBox1.Text = x
Once i get the answer for this, i can apply it for everything... I'm sure it's simple too and imma feel stupid. :-(
One of my Main Things is Querying WMI, and i get the ERROR '91' for the Label (This is in a For Each Loop) .. But its the same error, its like its makin me Declare Objects..(using Modules)
Label1.Caption = objItem.Antecedent
If Someone Could PLEASE Help me...
Use
form1.label1.caption = a
But make sure form1 is loaded
You get the error because Label1 and Label2, and your other controls for that matter do not exist in the scope of modGet.bas. They can only be referenced (the properties accessed or set), from with the form. The different error you get when you add Dim Label1 As Object is caused because an you defined Label1 as an Object, not as a Label, and an object does not have a Caption property. Unless you have a good reason for putting the GetNum sub in a .bas module move it into the form and it should work.
I modified the second example. It will modify the strings passed into it in a way that when execution passes back to the form you can assign the strings to your textboxes. I am against modifying controls on a form from another module because it goes against the idea of encapsulation.
'modGet.bas
Option Explicit
Public Function GetHello() As String
Dim strHello As String
strHello = "Hello"
GetHello = strHello
End Function
'frmMain.frm
'Option Explicit
Public Sub btnOpen_Click()
Label1.Caption = GetHello()
End Sub
Something a little different.
'MyModule.bas
Public Sub HelloWorld ByRef Value1 As String, ByVal Value2 As String)
On Error GoTo errHelloWorld
Value1 = "Hello"
Value2 = "World"
Exit Sub
errHelloWorld:
' deal with the error here
End Sub
'frmMain.frm
Option Explicit
Private Sub frmMain_Load()
Dim strText1 As String
Dim strText2 As String
HelloWorld(strText1, strText2)
Text1.Text = strText1
Text2.Text = strText2
End Sub
I also added basic error handling in the second example

How to pass the string value to function

I want to pass the string value to function
Function Code
Private Function Assign(Div As String)
sSQL = "Insert into table2 Select * from table1 Where Divi_Code = '" & Div & "'"
Rdoconn.Execute sSQL, rdExecDirect
End Function
Button Click Code
Dim Div as string
Div = "Hai,Howareyou"
Assign Div 'Getting Error as "ByRef arguement type mismatch"
The above code is shwoing error as Getting Error as "ByRef arguement type mismatch"
I tried the following code, and I am not getting any ByRef argument mismatch.
Private Function Assign(Div As String)
ssql = "Insert into table2 Select * from table1 Where Divi_Code = '" & Div & "'"
MsgBox ssql
End Function
Private Sub Command1_Click()
Dim Div As String
Div = "Hai,Howareyou"
Assign Div
End Sub
I am really puzzled why your code is giving you an error. However, there are a couple of things you should change in your code and I'm confident this will resolve your problem:
The function parameter should be declared ByVal. In VB6, parameters are ByRef by default unless specified. This means that the function call could have side-effects in the parent procedure if for any reason the parameter Div is modified. Always use ByVal unless you really need to modify the parameter value:
Private Function Assign(ByVal Div As String)
Is there any reason why you declared Assign as a Function? Are you intending to return a value? If not, you should use Private Sub instead of Private Function (and End Sub at the end). This is equivalent to using the void return type in C. For your reference, you should always define the return type of your functions in VB6, otherwise Variant will be assumed. The return type can be fined in functions using the "As" keyword at the end of the declaration:
Private Function Add(ByVal n1 as Integer, ByVal n2 As Integer) As Integer
One last thing I'd like to add is that you never, ever should concatenate variables to SQL queries like this. At the very least, the code will crash if the name contains an apostrophe (ex: try calling it with "I'm very well"), and at worst, you'll be opening up for SQL injection attacks where someone could use this to run specially crafted queries on your database. While I'm not familiar with RDO, you should check out MSDN - this article mentions how to create parameter queries with RDO.
To call a Function declared as
Private Function AssignDiv(Div As String, Dep As String)
you'd need something like
AssignDiv Div, "WhatEverDep"
Your
Assign Div
is completely wrong.
You changed your declaration to
Private Function AssignDiv(Div As String)
but the function's name is still wrong.
You changed your code again. Now names and parameters match, so if you still get an error, it's not caused by the code you published.
to begin with I don't understand why you are setting you Div value and then passing it into your function, you may as well pass it in directly on the button click, and then also I can't see that sSQL is actually defined as a string, please try the following code:
Public Function Assign(strDiv As String)
Dim sSQL As String
sSQL = "Insert into table2 Select * from table1 Where Divi_Code = '" & strDiv & "'"
Rdoconn.Execute sSQL, rdExecDirect
End Function
And then call from the button click as:
Private Sub Command1_Click()
Call Assign("Hai,Howareyou")
End Sub

Visual Studio Automation: Programatically get a project output directory

I want to programatically get a project output directory in a Visual Studio macro.
I managed to get a string of the path (through prj.ConfigurationManager.ActiveConfiguration.Properties and looking at property OutputDirectory) but this string may contain macros such as $(foo) where foo is defined in a property sheet or whatnot.
How do I resolve this output directory string to the 'real' directory?
I wrote this function for my macros which searches for full absolute output path by substring.
Function FindOutBinaryNameByExtension(ByVal prj As EnvDTE.Project, ByVal extName As String) As String
FindOutBinaryNameByExtension = Nothing
Dim cm As ConfigurationManager = prj.ConfigurationManager
If cm IsNot Nothing Then
Dim ac As Configuration = cm.ActiveConfiguration
For Each grpOut In ac.OutputGroups
If grpOut.DisplayName = "Primary output" Then
Dim lst As Array = grpOut.FileURLs
For i As Long = 0 To lst.Length - 1
Dim fileName As String = lst.GetValue(i)
If fileName.Contains(extName) Then
FindOutBinaryNameByExtension = fileName
Exit Function
End If
Next
End If
Next
End If
End Function

VB6 Runtime Type Retrieval

How can you obtain the Type (the name as a string is sufficient) of an Object in VB6 at runtime?
i.e. something like:
If Typeof(foobar) = "CommandButton" Then ...
/EDIT: to clarify, I need to check on Dynamically Typed objects. An example:
Dim y As Object
Set y = CreateObject("SomeType")
Debug.Print( <The type name of> y)
Where the output would be "CommandButton"
I think what you are looking for is TypeName rather than TypeOf.
If TypeName(foobar) = "CommandButton" Then
DoSomething
End If
Edit: What do you mean Dynamic Objects? Do you mean objects created with
CreateObject(""), cause that should still work.
Edit:
Private Sub Command1_Click()
Dim oObject As Object
Set oObject = CreateObject("Scripting.FileSystemObject")
Debug.Print "Object Type: " & TypeName(oObject)
End Sub
Outputs
Object Type: FileSystemObject
TypeName is what you want... Here is some example output:
VB6 Code:
Private Sub cmdCommand1_Click()
Dim a As Variant
Dim b As Variant
Dim c As Object
Dim d As Object
Dim e As Boolean
a = ""
b = 3
Set c = Me.cmdCommand1
Set d = CreateObject("Project1.Class1")
e = False
Debug.Print TypeName(a)
Debug.Print TypeName(b)
Debug.Print TypeName(c)
Debug.Print TypeName(d)
Debug.Print TypeName(e)
End Sub
Results:
String
Integer
CommandButton
Class1
Boolean
I don't have a copy of VB6 to hand, but I think you need the
Typename()
function... I can see it in Excel VBA, so it's probably in the same runtime. Interestingly, the help seems to suggest that it shouldn't work for a user-defined type, but that's about the only way I ever do use it.
Excerpt from the help file:
TypeName Function
Returns a String that provides information about a variable.
Syntax
TypeName(varname)
The required varname argument is a
Variant containing any variable except
a variable of a user-defined type.
This should prove difficult, since in VB6 all objects are COM (IDispatch) things. Thus they are only an interface.
TypeOf(object) is class probably only does a COM get_interface call (I forgot the exact method name, sorry).

Resources