Write the result of SQL-query in file with encoding UTF-8 without BOM

Скрипт позволяет выгрузить результат SQL-запроса (MS SQL Server) в текстовый файл с разделителями в кодировке UTF-8 без BOM.

Dim oSource
Dim oDatabase
Dim oUser
Dim oPassword
Dim conn
Dim cmd
Dim rs
Dim fs
Dim arr
Dim textStream
Dim FileName
Dim strLine, Str
Dim Res
Dim sep
Dim i
Dim dblQuate

'Enter settings for connecting to MS SQL database
oSource = "mssqlsrv"
oDatabase = "hwiproducts"
oUser = "hwiuser"
oPassword = "*******"

Set conn = CreateObject("ADODB.Connection")
conn.Open "Provider=SQLOLEDB;Data Source=" _
    & oSource & ";Trusted_Connection=Yes;Initial Catalog=" _
    & oDatabase & ";User ID=" & oUser & ";Password=" & oPassword & ""

Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = conn

'Place your SQL-Query
cmd.CommandText = "SELECT TYPENAME, " _
                 & "MDNAME, " _
                 & "SN, " _
                 & "STRIHCODE, " _
                 & "VENDOR, " _
                 & "convert(varchar(20), INDEMNITYD, 120) INDEMNITYD, " _
                 & "convert(varchar(20),GUARANT,120) GUARANT, " _
                 & "DEP " _
                 & "FROM [hwiproducts].[dbo].[productstores]" _
                 & "WHERE TYPEEQU = 'Printers'"

'Execute your SQL-Query
Set rs = cmd.Execute
 
'Specify the full path to the file to which we write the query result
FileName = "d:\PLANTRACE\HWI\Printers.csv"
 
Set fs = CreateObject("Scripting.FileSystemObject")

'Check the existence of the file and delete it (if necessary)
If fs.FileExists(FileName) Then
   fs.DeleteFile(FileName)
End If

Set textStream = fs.OpenTextFile(FileName, 8, True)

'Specifies the separator
sep = ","

Do Until rs.EOF
    
    'Count the number of fields
    ColCount = rs.Fields.Count - 1
    
    For i = 0 To ColCount
        'Add double quotes to values (if necessary)
        dblQuate = """"& rs(rs.Fields(i).Name) &""""
        
        'Form a string to write to the file
        strLine = strLine & sep & dblQuate
        
        If i = ColCount Then
            
            'Separator to remove from the beginning of the string
            Str = Replace(strLine,",","",1,1)
            
            'Convert string to UTF-8 without BOM and write it in file
            Res = StrConvert (Str, "Windows-1251", "UTF-8")
            textStream.WriteLine Res
            
            'When a string is writed then clean it
            strLine = ""
        End If
    Next
    
    'Next row from result query
    rs.MoveNext
Loop

'Close stream, command and connecting
textStream.Close
rs.Close
conn.Close

Function StrConvert(Text, FromCharset, ToCharset)
'What's: converts the string in encoding UTF8 without BOM
Dim Stream

Set Stream = CreateObject("ADODB.Stream")
    Stream.Type = 2
    Stream.Mode = 3
    Stream.Open
    Stream.Charset = ToCharset
    Stream.WriteText Text
    Stream.Position = 0
    Stream.Charset = FromCharset
    BOM = Stream.ReadText(3)

'Skip BOM bytes
If AscB(MidB(BOM, 1, 1)) = 239 And AscB(MidB(BOM, 2, 1)) = 187 _
                             And AscB(MidB(BOM, 3, 1)) = 191 Then
    Stream.Position = 3
 Set fOut = CreateObject("adodb.stream")
    fOut.Type = 2
    fOut.Mode = 3
    fOut.Open
    fOUT.WriteText Text
    StrConvert = fOUT.ReadText
Else
    StrConvert = Stream.ReadText
End If
 
End Function

Start the process when it is not running (by vbscript)

Иногда требуется проверить запущен ли процесс (например, notepad.exe) под пользователем (user1), чтобы случайно не запустить его дважды, или вообще запустить его, если он отсутствует в списке процессов. Я описал пример запуска java.exe для компиляции apex.war (запуска Oracle Apex listener 2.0.3), при условии, что база данных APEX (Oracle) работает и процесс не запущен. Для проверки запущен ли процесс, написал функцию SearchProcess, которая возвращает 1, если процесс запущен.

'(с) 19.05.2014
Dim ObjShell, Shell
Dim ObjProc
Dim StrORA
Dim dblist
Dim chekdir
Dim procname
Dim ownername
Dim Res
Dim JavaHome

'Указываем путь к java.exe нужно нам версии
JavaHome="c:\Program Files\Java\jdk1.6.0_18\bin\java.exe"

'Подключение к базе (Oracle)
Set ObjShell = CreateObject("WScript.Shell")
WScript.Sleep 600
StrORA = "sqlplus /@APEX as sysdba @x:\apexlistener\connect.sql" 'файл connect.sql содержит следующий код: select sysdate from dual; exit
Set ObjProc = ObjShell.Exec(StrORA)

input = ""
strOutput = ""
'Читаем output нашего соединения к базе
Do While Not ObjProc.StdOut.AtEndOfStream
input = input & vbCrLf & ObjProc.StdOut.ReadLine
Loop

'Если соединение завершилось успешно
If InStr(input, "SYSDATE") Then
'Проверяем запущен ли процесс под этим владельцем
Res = SearchProcess("java.exe", "orauser")
If Res 1 Then
StrORA = JavaHome & " -Dapex.home=x:\apex\8090 -Dapex.port=8090 -Dapex.images=x:\apex\images -jar apex.war"
Set ObjProc = ObjShell.Exec(StrORA)
End IF
Else
'WScript.Echo "ORACLE is DISABLE!"
End If

Function SearchProcess(procname, ownername)
'(c) 19.05.2014
'What's: проверяет запущен ли процесс на компьютере и кто его владелец
' procname - имя процесса
' ownername - имя пользователя, под кем запущен процесс

Dim strComputer ' Имя компьютера
Dim objService ' Объект SWbemServices
Dim colProcesses ' Коллекция экземпляров класса WMI
Dim objProcess ' Элемент коллекции
Dim WshShell ' Объект WshShell
Dim cnt 'счетчик
Dim Return
Dim strNameOfUser

Set WshShell = WScript.CreateObject("WScript.Shell")

' "." - локальный компьютер
strComputer = "."

' Подключаемся к пространству имен WMI
Set colProcesses = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2").ExecQuery("SELECT * FROM Win32_Process")

if colProcesses.Count > 0 Then

'Перебираем коллекцию
For Each objProcess in colProcesses

'Проверяем искомый процесс
If objProcess.Name = procname Then
' Проверяем владельца процесса
Return = objProcess.GetOwner(strNameOfUser)
If Return = 0 Then
If strNameOfUser = ownername Then
SearchProcess = 1
'WScript.Echo "Process " & objProcess.Name & " is owned by " & "\" & strNameOfUser & "."
End If
End If
End If
Next
End If

End Function