Sfc сканер для всех, кто хочет внести свои пожелания или потестировать сборки

Кирилл

Команда форума
Администратор
Ассоциация VN
Сообщения
14,069
Реакции
5,784
Привет.
Собственно решил, что возможно людям будет интересно участие в создании более гибкой версии скрипта sfc /scannow ?
Собрал стартовый код, который выполняет саму проверку, пока базовую.

Считай, с нуля - все хотелки можно учитывать сразу...
Вариант на питоне

Python:
import wx
import os
import shutil

#Текущий катлог
StrDir_ = os.getcwd()
#Системная директория
WinDir_ = os.getenv('windir')
#Путь к кталогу CBS
WinCbs_ = WinDir_ + '\\Logs\\CBS\\'
sf_pr='C:\\Windows\\system32\\sfc.exe /scannow'

#Функция проверки наличия каталога
def Dir_ (str_):
    str_ = StrDir_ + '\\' + str_
    return (os.path.isdir(str_))

#Проверка существования файла
def File_Exist(files_):
    print(os.path.exists(files_))

#Проверяем хитектуру системы
if ("64" in os.getenv('PROCESSOR_ARCHITECTURE')) or ("64" in os.getenv('PROCESSOR_ARCHITEW6432')):
    arh = "64"

else:
    arh ="32"




class scanOs(wx.Frame):
    def __init__(self):
         wx.Frame.__init__(self, None, -1, 'SFC Scan',
                  size=(500, 200))
         panel = wx.Panel(self, -1)
         self.button = wx.Button(panel, -1, "Start Scan SFC", pos=(50, 20))
         self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)
         self.button.SetDefault()


    #Функция, вызываемая при нажатии левой кнопкой мыши
    def OnClick(self, event):
        #Если каталог Log в текущем катлоге отсутствует - создаем
        if Dir_('Log'):
            print('Рабочий каталог обнаружен:')
            print(StrDir_ + '\Log')
            print()
        else:
            os.mkdir('Log')
            print('Создан рабочий каталог: ' + StrDir_ )
            print('')



        #Проверяналичие файла- логаб если найден - бэкапим
        if os.path.exists(StrDir_ + '\Log' + 'sfcdoc.log'):
            os.rename(StrDir_ + '\Log' + 'sfcdoc.log', StrDir_ + '\Log' + '\sfcdoc.bak.log')
            print('Создана резервная копия лога')
            print('')

        #Завершаем процесс TiWorker, если он есть
        os.system('C:\\Windows\\system32\\taskkill /im TiWorker.exe /f')

        #Меняем текст кнопки
        if self.button.GetLabel() == 'Start Scan SFC':
            self.button.SetLabel("Scanning SFC...")
            wx.Execute(sf_pr,wx.EXEC_SYNC, callback=None)
            #Копируем cbs.log
            shutil.copy(WinCbs_ + 'cbs.log', StrDir_ + '\Log')
 
            self.button.SetLabel("Start Scan SFC")
            #Завершаем процесс TiWorker, если он есть
            os.system('C:\\Windows\\system32\\taskkill /im TiWorker.exe /f')
        else:
            self.button.SetLabel("Start Scan SFC")

if __name__ == '__main__':
    app = wx.App()
    frame = scanOs()
    frame.Show()
    app.MainLoop()

Вариант на vb6:
VB.NET / VBA:
Option Explicit

Private Const MAX_PATH As Long = 260&

Private Type PROCESSENTRY32
    dwSize As Long
    cntUsage As Long
    th32ProcessID As Long
    th32DefaultHeapID As Long
    th32ModuleID As Long
    cntThreads As Long
    th32ParentProcessID As Long
    pcPriClassBase As Long
    dwFlags As Long
    szExeFile As String * MAX_PATH
End Type

Private Declare Function CreateToolhelp32Snapshot Lib "kernel32.dll" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
Private Declare Function Process32First Lib "kernel32.dll" (ByVal hSnapshot As Long, ByRef lppe As PROCESSENTRY32) As Long
Private Declare Function Process32Next Lib "kernel32.dll" (ByVal hSnapshot As Long, ByRef lppe As PROCESSENTRY32) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function lstrcmpi Lib "kernel32.dll" Alias "lstrcmpiW" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32.dll" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

Private Const TH32CS_SNAPPROCESS        As Long = 2
Private Const SYNCHRONIZE               As Long = &H100000
Private Const INFINITE                  As Long = -1
Private Const INVALID_HANDLE_VALUE      As Long = -1
Private Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function IsIconic Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function FlashWindow Lib "user32" (ByVal hwnd As Long, ByVal bInvert As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)


Private Declare Function GetProcessIoCounters Lib "kernel32.dll" (ByVal hProcess As Long, IoCounters As Any) As Long
Private Declare Function GetCurrentProcess Lib "kernel32.dll" () As Long
Private Type IO_COUNTERS
    ReadOperationCount As Currency
    WriteOperationCount As Currency
    OtherOperationCount As Currency
    ReadTransferCount As Currency
    WriteTransferCount As Currency
    OtherTransferCount As Currency
End Type

Private Type tagINITCOMMONCONTROLSEX
  dwSize  As Long
  dwICC  As Long
End Type

Private Declare Function InitCommonControlsEx Lib "comctl32.dll" (lpInitCtrls As tagINITCOMMONCONTROLSEX) As Boolean

Dim IO_C As IO_COUNTERS
Dim selfPatch_ As String              'Переменная хранения относительных путей
Dim WshShell As Object                '
Dim objWMIService, colProcesses       '
Dim Process                           'Тут хранится имя процессов,с которыми планируем работать
Dim runas                             'Глагол для запуска программ /позже переназвать и вставить как парметр функции
Dim WinDir_ As String                 'Директория установки Windows
Dim WinDrv_ As String                 'Диск, на котором установлена система
Dim sProcName As String
Dim PID As Long
Dim hProc As Long


Private Sub Form_Initialize()
  On Error Resume Next
  Dim ICC As tagINITCOMMONCONTROLSEX

  ' Enable visual styles
  With ICC
      .dwSize = Len(ICC)
      .dwICC = &HFF& 'http://www.geoffchappell.com/studies/windows/shell/comctl32/api/commctrl/initcommoncontrolsex.htm
  End With
  InitCommonControlsEx ICC
End Sub




Public Sub Command1_Click()

If Command1.Caption Like "Start scan SFC" Then
    Command1.Enabled = False
    Command1.Caption = "Ожидайте..."
    Call ff("taskkill.exe", "/IM TiWorker.exe /f", "0")
    Sleep 1000
    Call ff("sfc.exe", "/scannow", "1")
   
Else
    KillProc ("sfc.exe")
    Sleep 1000
    Command1.Caption = "Start scan SFC"
    Call ff("taskkill.exe", "/IM TiWorker.exe /f", "0")
End If
End Sub




'Функция проверки наличия файла в каталоге
Public Function f_search(f_ As String) As Boolean

If Trim$(Dir(f_)) <> "" Then
'Файл в директории существует
    f_search = True
Else
    f_search = False
End If
End Function




'Запуск процессов с аргументами
Public Sub ff(self As String, arg_ As String, size_ As String)

'Проверяем наличие запускаемого объекта по адресу: \windows\Sysnative\
'Если есть - назначем этот путь рабочей директорией
If f_search(WinDir_ & "\Sysnative\" & self) = True Then
    selfPatch_ = WinDir_ & "\Sysnative\"
Else
    selfPatch_ = WinDir_ & "\System32\"
End If

Dim Start
    Start = Shell(selfPatch_ & self & Chr(32) & arg_, size_)
    Sleep 2000 'Выдерживаем паузу 2 секунды
   
Call IfProc_(self)
'ооо тут стопанулся - последовательность старта функции
End Sub





'Убиваем процесс по имени БЕЗ принудительного завершения
Private Sub KillProc(KlPr_ As String)
For Each Process In GetObject("winmgmts:").ExecQuery("Select * from Win32_Process")
                If Process.Caption Like KlPr_ Then
                        Process.Terminate
                End If
        Next
End Sub

Private Sub IfProc_(self)
sProcName = self
Sleep 1000 'Выдерживаем паузу 1 секунду

    If IsRunned(sProcName, PID) Then
    'попробовать замостить эту функцию для проверки наличия процесса
        hProc = OpenProcess(SYNCHRONIZE, False, PID)
       
        If hProc > 0 Then
            Sleep 1000 'Выдерживаем паузу 1 секунду
           
            Sleep 1000 'Выдерживаем паузу 1 секунду
            Call WaitForSingleObject(hProc, INFINITE)
        End If
        Text1.Text = Text1.Text & vbCrLf & "Процесс " & sProcName & " завершен." & vbCrLf
        If self Like "sfc.exe" Then Call ff("taskkill.exe", "/IM TiWorker.exe /f", "0")
        Command1.Caption = "Start scan SFC"
        Command1.Enabled = True
    Else
        If self Like "taskkill.exe" = False Then
            Text1.Text = Text1.Text & vbCrLf & "Процесс " & sProcName & " не запущен" & vbCrLf
        End If
    End If
End Sub

Private Sub Form_Load()
WinDir_ = Environ("WinDir")
WinDrv_ = Environ("SystemDrive")
End Sub

Function IsRunned(Optional ByRef ProcessName As String, Optional ByRef ProcessID As Long) As Boolean
    ' Запущен ли процесс, указанный по имени или ProcessID
    ' (регистр символов не учитывается)
    ' Если процесс найден, в переменную ProcessID передается PID найденного процесса (если поиск велся по имени),
    ' либо в переменную ProcessName возвращается имя найденного процесса (если поиск велся по PID).

    Dim hSnap   As Long
    Dim pe      As PROCESSENTRY32

    If Len(ProcessName) = 0 And ProcessID = 0 Then Exit Function

    hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)

    If hSnap = INVALID_HANDLE_VALUE Then Exit Function

    pe.dwSize = Len(pe)

    If Process32First(hSnap, pe) Then
        Do
            If Len(ProcessName) = 0 Then
                If pe.th32ProcessID = ProcessID Then
                    IsRunned = True
                    ProcessName = Left$(pe.szExeFile, InStr(pe.szExeFile, vbNullChar) - 1)
                    Exit Do
                End If
            Else
                If lstrcmpi(StrPtr(pe.szExeFile), StrPtr(ProcessName)) = 0 Then
                    IsRunned = True
                    ProcessID = pe.th32ProcessID
                    Exit Do
                End If
            End If
        Loop While Process32Next(hSnap, pe)
    End If
    CloseHandle hSnap
End Function
 

Вложения

  • test.7z
    6.9 KB · Просмотры: 10
Последнее редактирование:
Можно еще готовый exe собрать - но на сейчас там и без тестов все будет работать, поэтому пока только код запостил...
 
Python:
Traceback (most recent call last):
  File "Main.py", line 1, in <module>
    import wx
ModuleNotFoundError: No module named 'wx'
Отсутствует данный модуль, надо установить wxPython. Если я правильно помню
else: arh ="32" sf_pr='C:\Windows\sysnative\\sfc.exe /scannow'
Тут помоем не хватает \?
 
@Кирилл, для проверки целостности файлов устанавливать VC++ redistributable?
А что с почти готовым проектом на VB, забросил?
Какие шансы тогда у тебя будут с новым языком?
Vc++ я как то не учел))
От скрипта на cmd надо уйти, а питон оказался и правда любопытный и относительно не сложный.
С vb есть сложности - чем дальше углубляешься, тем более академические знания нужны.
Куча нюансов и особенностей, как системы так и среды...хотел попробовать что то новое просто.

Отсутствует данный модуль, надо установить wxPython. Если я правильно помню

Тут помоем не хватает \?
Ошибка из за модуля, да.
Когда в программу собираешь он в комплекте должен быть...
Сам код я в итоге сократил сильно - редиректы не нужны, многие условия тоже.
Утром до компа дойду заменю сам код.
Да, сборка в exe на питоне нужна раздельно для 32 и 64 систем - прям минус такой.

Если без установки чего либо дополнительно не удастся обойтись, то на питоне это делать бессмысленно будет.
Я так понял он подходит либо для больших проектов, либо для выполнения на стороне сервера с установленной средой.
Но штука, конечно, крутая.
Особенно в плане простоты работы с информацией.
 
Последнее редактирование:
Можно поподробней кто это и как мешает сфц? А то не впервые вижу
TiWorker (Windows Modules Installer Worker) это один из процессов, необходимый для работы «Центра обновления Windows», который устанавливает все актуальные обновления на ПК
кто это и как мешает сфц?
Это скорей всего связано с тем, что TiWorker.exe начинает сжимать старые файлы и sfc в этот момент, будет обнаруживать эти действия изменения файлов и пытаться восстановить данные файлы.
 
Последнее редактирование:
Можно поподробней кто это и как мешает сфц? А то не впервые вижу
TiWorker (Windows Modules Installer Worker) это один из процессов, необходимый для работы «Центра обновления Windows», который устанавливает все актуальные обновления на ПК
Если не вдаваться в технические подробности - то процесс TiWorker.exe запускается совместно с sfc.exe и выполняет определенные задачи.
Когда вы запустили sfc один раз - нормально все отработает, но если по каким то причинам у вас был этот процесс запущен ранее или некорректно завершен, то и новая проверка у вас может не запуститься.
Вы получите разного рода сообщения, например: программа sfc не может выполнить запрошенную операцию потому что ... ну и отсылка на параллельные задачи.
Убив TiWorker.exe мы завершаем целый ряд задач, которые могут отразиться на результате работы sfc или в принципе на его работе, без перечисления большого количества условий.
Обновил скрипт - можно в принципе уже парсить лог начинать, на доступных мне машинах все работает на ура.
 
Последнее редактирование:
Ну и питон для этого не подошел - действительно нужны танцы с бубном, что бы все работало на любой машине.
Вечером выложу проект на vb и тему перенесу, если это окажется интересным и кто то захочет вести разработку совместно - я возражать не стану, только за)
Уровень подготовки желающих - любой, кто то умеет писать код, у кого то могут быть идеи а у кого то есть просто комп на котором можно протестировать программу)
 
Собрал базовый пакет на vb - по мере появления замечаний буду доводить тогда его.
Пока - только проверка sfc стандарт, убрал все лишнее.

VB.NET / VBA:
Private Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function IsIconic Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function FlashWindow Lib "user32" (ByVal hwnd As Long, ByVal bInvert As Long) As Long
Private Declare Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As Long)
 
 
 
Private Declare Function GetProcessIoCounters Lib "kernel32.dll" (ByVal hProcess As Long, IoCounters As Any) As Long
Private Declare Function GetCurrentProcess Lib "kernel32.dll" () As Long
Private Type IO_COUNTERS
    ReadOperationCount As Currency
    WriteOperationCount As Currency
    OtherOperationCount As Currency
    ReadTransferCount As Currency
    WriteTransferCount As Currency
    OtherTransferCount As Currency
End Type
Dim IO_C As IO_COUNTERS
 
 
Private Type tagINITCOMMONCONTROLSEX
  dwSize  As Long
  dwICC  As Long
End Type

Private Declare Function InitCommonControlsEx Lib "comctl32.dll" (lpInitCtrls As tagINITCOMMONCONTROLSEX) As Boolean

Private Sub Form_Initialize()
  On Error Resume Next
  Dim ICC As tagINITCOMMONCONTROLSEX

  ' Enable visual styles
  With ICC
      .dwSize = Len(ICC)
      .dwICC = &HFF& 'http://www.geoffchappell.com/studies/windows/shell/comctl32/api/commctrl/initcommoncontrolsex.htm
  End With
  InitCommonControlsEx ICC
End Sub
 
Private Sub Form_Load()
Dim selfPatch_ As String 'Переменная хранения относительных путей
Dim WshShell As Object
Dim objWMIService, colProcesses
Dim Process As String

End Sub
 
Public Sub Command1_Click()
If Command1.Caption Like "Start scan SFC" Then
    KillProc ("TiWorker.exe")
    Sleep 3000
    Call ff("sfc.exe", "/scannow")
    Command1.Caption = "Stop Scanning?"
Else
    KillProc ("sfc.exe")
    Sleep 3000
    KillProc ("TiWorker.exe")
    Command1.Caption = "Start scan SFC"
End If
End Sub
 
 
Public Function f_search(f_ As String) As Boolean

If Trim$(Dir(f_)) <> "" Then
'Файл в директории существует
    f_search = True
Else
    f_search = False
End If
End Function

Public Sub ff(self As String, arg_ As String)

'Проверяем наличие запускаемого объекта по адресу: c:\windows\Sysnative\
'Если есть - назначем этот путь рабочей директорией
If f_search("c:\windows\Sysnative\" & self) = True Then selfPatch_ = "c:\windows\Sysnative\"

    CreateObject("Shell.Application").ToggleDesktop 'Теперь свернем все активные окна, что бы не мешались)
    CreateObject("Shell.Application").ShellExecute self, Chr(32) & arg_, selfPatch_, runas, 1 'прогрмма, аргумент (с пробелом), рабочий каталог, глагол, режим окна
    Sleep 3000 'Выдерживаем паузу 3 секунды
  
Process = self
Set objWMIService = GetObject("winmgmts:")
Set colProcesses = objWMIService.ExecQuery("Select * from Win32_Process where name='" & Process & "'")
If colProcesses.Count Then
    Print ("Процесс запущен успешно")
Else
    Print ("Не удалось запустить процесс")
End If
End Sub

Private Sub KillProc(KlPr_ As String)
For Each Process In GetObject("winmgmts:").ExecQuery("Select * from Win32_Process")
                If Process.Caption Like KlPr_ Then
                        Process.Terminate
                End If
        Next
End Sub

Сейчас процесс TiWorker (Windows Modules Installer Worker) не трогаю - можно увидеть разницу
 
Последнее редактирование:
Вы написали язык на основе VB?

Скинь мне программу на эту( в ЛС). Чтобы Я, мог понять его как вы его собирали и комплировали.
Как программа называется, которы вы пишите?
 
Вы написали язык на основе VB?
Что? Нет, я написал программу на языке vb
Как программа называется, которы вы пишите?
Замена этому проекту
Исходный код в спойлере, смотрите

Обновил код, залил свежий файл
 

Вложения

  • test_sfc.7z
    5.6 KB · Просмотры: 7
Последнее редактирование:
Я, имею ввиду какой программой который вы пользуетесь утилитой или средство для написания VB? Через какой программой?
 
Последнее редактирование:
Cам написал Код проще на VBS...: Похожи на .VB, это как сокращенный, код не требуется множеств кодов.

VB.NET / VBA:
Option Explicit

' Run as Admin

If Not WScript.Arguments.Named.Exists("elevate") Then

    CreateObject("Shell.Application").ShellExecute WScript.FullName _

    , WScript.ScriptFullName & " /elevate", "", "runas", 1

    WScript.Quit

End If

Dim ws,MyCommand,Execution

Set ws = createobject("wscript.shell")

MyCommand = "SFC /SCANNOW"

Execution = ws.run(MyCommand,1,False)
 
Последнее редактирование модератором:
У пайтона все же есть преимущества. Кнопки, тартл, интерфейс

Ты, Каким образом?????

Python:
import subprocess
from os import system
или
import subprocess
subprocess.Popen( ['runas', '/user:Administrator', 'sfc /scannow'] )

print('1. sfc scan')
print('2. DISM')

key = int(input('Input your choice: '))
if key == 1:
    system("sfc /scannow")
elif key == 2:
    system("DISM /Online /Cleanup-Image /CheckHealth")

P.S
Для вам сюрприз @Кирилл Требуем доработки Python... Специально написал для тебя.
 
Последнее редактирование:
Назад
Сверху Снизу