Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Japanese characters in the filesystem

Status
Not open for further replies.

kmcferrin

MIS
Jul 14, 2003
2,938
US
OK, I thought I'd take another stab at this. I have a script that is supposed to scan a filesystem and generate a list of files that meet certain criteria. The script works flawlessly for everything it is intended to, except when it encounters Japanese characters. Some of the directories in this filesystem have Japanese names, and every time I get to one the script bombs out with:

(129, 10) Microsoft VBScript runtime error: Invalid procedure call or argument

This is the line where the script tries to write the name of the directory (which is in Japanese) to an output file. There has to be some way to work around this, but I can't find it. Installing Japanese support on the PC and server makes no difference, the error still occurs.

Does anyone out there know of a way of handling Japanese in VBScript?
 
Post code please. I suspect you need to open the file for unicode but it would help to see what you currently do.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
Code:
  Script that iterates through a directory tree to locate all files that have
'  a 'last accessed' date older than a certain date (or age in days).  It then
'  logs the files and their full path to an output file of your choosing.
'
'  DIRECTIONS:  
'  Use with command line arguments.
'  /path: followed by the full directory path to the target directory
'  /age: followed by the age of the files in days
'  /date: followed by the cutoff date in the dd/mm/yyyy format
'  /output: followed by the path and name of the output file (i.e., c:\output.txt)
'         if /output: is not specified it will default to c:\output.txt

Option Explicit

'On Error Resume Next

Dim strTargetDir, strErrorFile, strOutputFile, intCutoffAge, intOldLogExists, objFSO, objFile, strNotificationMessage, colNamedArguments, _
    strTargetDate, intFileCount, intFileSizeCount, intFileSize
                
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Const OverwriteExisting = True

intFileCount = 0
intFileSizeCount = 0
intFileSize = 0

Set colNamedArguments = WScript.Arguments.Named

If colNamedArguments.Exists("output") Then
    strOutputFile = colNamedArguments.Item("output")
Else
    strOutputFile = "c:\output.txt"
End If

If colNamedArguments.Exists("path") Then
    strTargetDir = colNamedArguments.Item("path")
Else
    Wscript.Echo "Please specify a target directory via the /path: command line argument."
    Wscript.Quit 1
End If

If colNamedArguments.Exists("date") and colNamedArguments.Exists("age") Then
    Wscript.Echo "You cannot use the /date: and /age: command line arguments at the same time.  Please use one or the other, but not both."
    Wscript.Quit 1
Else
End If

If colNamedArguments.Exists("date") Then
    strTargetDate = CDate(colNamedArguments.Item("date"))
    intCutoffAge = DateDiff("d", strTargetDate, Now)
Else
End If

If colNamedArguments.Exists("age") Then
    intCutoffAge = CInt(colNamedArguments.Item("age"))
Else
End If

If intCutoffAge = "" and strTargetDate = "" Then
    Wscript.Echo "Please specify either a cutoff date or age in days using the /date: or /age: command line argument."
    Wscript.Quit 1
Else
End If



Set objFSO = CreateObject("Scripting.FileSystemObject")

' Checks for old output file and deletes it, then creates a new one
If objFSO.FileExists(strOutputFile) Then 
	objFSO.DeleteFile(strOutputFile)
Else
End If
Set objFile = objFSO.CreateTextFile(strOutputFile, OverwriteExisting) 
objFile.Close

Wscript.Echo "Directory Tree Crawler started at " & Now
Wscript.Echo " Hit CTRL-C to exit."
Wscript.Echo "Target:   " & strTargetDir 
Wscript.Echo "Date:     " & strTargetDate
Wscript.Echo "Age:      " & intCutoffAge

CrawlTree strTargetDir
intFileSizeCount = FormatNumber(intFileSizeCount / 1024, 2)
Wscript.Echo intFilecount & " files at " & intFileSizeCount & " kilobytes meet the selected criteria."
Set objFile = objFSO.OpenTextFile(strOutputFile, ForAppending)
objFile.Writeline intFilecount & " files at " & intFileSizeCount & " kilobytes meet the selected criteria."
objFile.Close

Sub CrawlTree(strTargetDir)
    Dim objFolder, arrFolders, objFiles, Item, Item2
    Set objFolder=objFSO.GetFolder(strTargetDir)
    Set arrFolders=objFolder.SubFolders
    Set objFiles=objFolder.Files

    ' Get all sub-folders in this folder
    For Each Item In arrFolders
        If Right(Item, 3) = "-NP" Then
            Wscript.Echo Now & " -- " & item & " ends with -NP.  Skipping directory tree."
        ElseIf Right(Item, 10) = "ANOTHER" Then
            Wscript.Echo Now & " -- " & item & " ends with ANOTHER.  Skipping directory tree."
        Else
            If Len(Item) < 256 Then
                CrawlTree(item)
            Else
                Wscript.Echo Now & " -- " & item & " is deeper than 256 characters (" & Len(Item) & " characters).  Skipping directory tree."
            End If
        End If
    Next
    Item2=0

    'Scan through  the files collection, find files older than the target age and adds to output.
    For Each Item2 in objFiles
    Dim strAccessDate, strCreatedate, objFileName, intDaysOld
    Set objFileName = objFSO.GetFile(Item2)
    strAccessDate = objFileName.DateLastAccessed
    intDaysOld = DateDiff("d", strAccessDate, Now)
    If intDaysOld > intCutoffAge Then
        Wscript.Echo Now & " -- " & objFileName.Path & " is " & intDaysOld & " days old." & "  Depth=" & Len(objFileName.Path)
        If Len(objFileName.Path) < 256 Then
            Set objFile = objFSO.OpenTextFile(strOutputFile, ForAppending)
	        objFile.Writeline objFileName.Path
	        objFile.Close
            intFileCount = intFileCount + 1
            intFileSize = objFileName.Size
            intFileSizeCount = intFileSizeCount + intFileSize
        Else
            Wscript.Echo Now & " -- " & item & " is deeper than 256 characters (" & Len(Item) & " characters).  Skipping directory tree."
        End If
    Else
    End If
    Next
End Sub
 
try changing this:

Set objFile = objFSO.CreateTextFile(strOutputFile, OverwriteExisting)

to this:

Set objFile = objFSO.CreateTextFile(strOutputFile, OverwriteExisting[red], true[/red])

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
OK, I modified the section that creates the output file to read:

Code:
' Checks for old output file and deletes it, then creates a new one
If objFSO.FileExists(strOutputFile) Then 
	objFSO.DeleteFile(strOutputFile)
Else
End If
Set objFile = objFSO.CreateTextFile(strOutputFile, OverwriteExisting, true) 
objFile.Close

But I still get the same error message.
 
Read the docs on OpenTextFile. You will need to tell it to use unicode as well I would imagine.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
Hmm...I did find the TriState value for opening Unicode files, you apparently need to use a "-1" argument on the OpenTextFile command. Unfortunately, I still get the same error, AND now the output file appears to be all in Japanese.

 
At this point I would be happy if I could just detect the directories with Japanese characters in their names so that I could skip them. I can always come back later and do some cleanup, but at the moment I'm on a bit of a deadline.

Any suggestions on that angle?
 
Unfortunately this specific issue is not one that I have had to deal with before so I am operating off general knowledge. With luck someone that has dealt with a similar issue will wander along.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
Well, I found a bit of a work-around. If I take the directory name or filename I can perform an "Asc(string)" on it to get the ASCII value of the first character, then an "AscB(string)" on it to get the ANSI value of the first character, then compare them. If they aren't the same then they are Unicode, which means I can skip them...for now. At least the script doesn't die, but it still doesn't check those directories.
 
And I also managed to get an answer form one of our developers. Apparently the FSO object in vbscript can only deal with single-byte characters, which excludes Japanese. I'm told that if you re-write everything in .NET you can use the System.IO library to do it.

Makes me wonder how the Japanese write management scripts...
 
Good question. That also means that Powershell would be able to handle it.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
Yeah, I looked at Powershell a little while back, but ran into related issues. I'm by no means a super-genius when it comes to VBScript, but I am a total newbie at PS and I didn't have time to learn it...this time.
 
[1]
>Set objFile = objFSO.CreateTextFile(strOutputFile, OverwriteExisting)
>objFile.Close

You don't need that (see [2]), but it does no harm neither. So you can just delete them.

[2] The main thing is that every time you use this line in various sub's (a couple of instances), you change it to the appropriate one.

>Set objFile = objFSO.OpenTextFile(strOutputFile, ForAppending)
[tt]Set objFile = objFSO.OpenTextFile(strOutputFile, ForAppending,[blue]true[/blue],[red]true[/red])[/tt]

The last true (or vbtrue or -1) is the unicode format directive (and the file will be created with the correct bom). The last but one true is to create a new file when it does not exist, hence, the part [1] will not need and the first instance when it encounts opentextfile, the file will be created.
 
Ah! I'll have to try that when I get to work to see how it goes.

Thanks for the tip!
 
Use ascw instead of asc or ascb for detecting Japanese chars.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top