none
Вывод результатов Invoke-CMReport в консоль или файл RRS feed

  • Вопрос

  • Приветствую!

    Есть ли возможность получить вывод команды Invoke-CMReport в консоле или файле?

    Делал 

    Invoke-CMReport-ReportPath"Users/Computers for a specific user name"-ReportParameter@{"user name"="test"} -OutputFormatcsv

    Но в конце он запрашивает подтверждение сохранения, то есть в скрипт не запихнуть.

    Или может быть есть другие способы получить вывод результатов отчетов SCCM в консоле Powershell?

    7 июня 2018 г. 12:57

Ответы

  • Коллега, я слабо понимаю, что делает этот скрипт, но это то, что нужно :)

    А с Invoke-CMWmiQuery или Invoke-CMQuery вы не работали?

    То есть веб запрос это по сути такой же WQL запрос к сиквельной базе SCCM.

    О, это просто:

    Invoke-CMWmiQuery - это просто обёртка над WMI.

    WMI-классы не полностью повторяют таблицы/вьювки (но логически очень между собой похожи), поэтому требуется некоторая адаптация и порой, в связи с ограниченностью языка запросов WMI (WQL), некоторой изобретательность :)

    Например, во sql-вьювке v_R_System (fn_rbac_R_System - это просто функция под вьювку v_R_System, с учётом ccm-прав (rbac) обратившегося пользователя), нет поля "User_Name0", есть например "LastLogonUserName". И если опираться на него то всё очень просто:

    $SearchUser = 's-korotkov'
    $query = @"
    select 
        LastLogonUserName
        ,NetbiosName
        ,OperatingSystemNameandVersion
    FROM SMS_R_SYSTEM
    WHERE LastLogonUserName = '$SearchUser'
    "@
    Invoke-CMWmiQuery -Query $query | ft 

    Чуть сложнее. Связь пользователя и компьютера через механизм UDA (User Device Affinity)

    $query = @"
    select 
        SMS_R_SYSTEM.NetbiosName
        ,SMS_R_SYSTEM.OperatingSystemNameandVersion
        ,SMS_R_User.UserName
        ,SMS_R_User.UniqueUserName
    from SMS_R_System
        JOIN SMS_UserMachineRelationship ON SMS_R_System.ResourceID = SMS_UserMachineRelationship.MachineResourceID
        JOIN SMS_R_User ON SMS_UserMachineRelationship.UniqueUserName = SMS_R_User.UniqueUserName
    WHERE SMS_R_User.UserName = '$SearchUser'
    "@
    
    $Res = Invoke-CMWmiQuery -Query $query
    $Res | select @{n="NetbiosName"; e={$_.SMS_R_SYSTEM.NetbiosName}}, @{n="UserName"; e={$_.SMS_R_User.UserName}},@{n="OS Name"; e={$_.SMS_R_SYSTEM.OperatingSystemNameandVersion}}




    9 июня 2018 г. 17:48
    Модератор
  • Запрос у нас есть, осталось только разобраться как это делается.

    в зависимости от того что вы хотите делать,

    вы можете обойтись без командлета, и получить результат в формате atom (xml)

    PS C:\> $u = "http://ssrs-server.domain.local/ReportServer?%2FConfigMgr_M02%2F%D0%9F%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B8%2F%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D1%8B%20%D0%B4%D0%BB%D1%8F%20%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE%20%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F&UserFilter=s-korotkov&variable=s-korotkov&rs%3AParameterLanguage=&rs%3ACommand=Render&rs%3AFormat=ATOM&rc%3AItemPath=Table0"
    $URL = [System.Net.WebUtility]::HtmlDecode($u)
    ## '&rc:Encoding=UTF-7'
    $Response = Invoke-WebRequest -Uri ($URL + '&rc:Encoding=UTF-7') -UseDefaultCredentials -ContentType 'application/atom+xml' -ErrorAction Continue -ErrorVariable err -WarningVariable warn
    [xml]$XmlCurrent = $Response.Content
    
    $ns = @{
        d  = "http://schemas.microsoft.com/ado/2007/08/dataservices";
        m  = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
        '' = "http://www.w3.org/2005/Atom";
    }
    $Cur = Select-Xml $XmlCurrent -Namespace $ns -XPath '//m:properties'
    $Cur | select -ExpandProperty Node | ft Details_Table0_User_Name0, Details_Table0_Netbios_Name0, Details_Table0_Operating_System_Name_and0
    
    Details_Table0_User_Name0 Details_Table0_Netbios_Name0 Details_Table0_Operating_System_Name_and0
    ------------------------- ---------------------------- -----------------------------------------
    s-korotkov                S-KOR-W10-ENT                Microsoft Windows NT Workstation 10.0
    s-korotkov                S-KOR-W10-PRO                Microsoft Windows NT Workstation 10.0
    s-korotkov                S-KOR-W7-X64                 Microsoft Windows NT Workstation 6.1
    s-korotkov                S-KOR-W7-X86                 Microsoft Windows NT Workstation 6.1
    s-korotkov                S-KOR-W81-X64                Microsoft Windows NT Workstation 6.3
    s-korotkov                S-KOR-W81-X86                Microsoft Windows NT Workstation 6.3

    Как получить ссылку только на таблицу с данными:

    сформируйте отчёт, в панели инструментов нажмите "экспортировать в поток данных", откройте полученный *.atomsvc - файл, последняя ссылка - та, которая нужна.

    Надо будет только приноровиться к работе с xml объектами :)


    Грамотная постановка вопроса - уже 50% решения.
    SCCM User Group Russia на FaceBook и в Telegram


    8 июня 2018 г. 10:35
    Модератор
  • Коллега, я слабо понимаю, что делает этот скрипт, но это то, что нужно :)

    А с Invoke-CMWmiQuery или Invoke-CMQuery вы не работали?

    То есть веб запрос это по сути такой же WQL запрос к сиквельной базе SCCM.

    ах, да...

    Invoke-CMQuery - тут вообще всё просто и гениально, вы пишете запрос (query) в консоли: \Monitoring\Overview\Queries\

    а командлетом Invoke-CMQuery выполняете его и получаете результат.

    Invoke-CMQuery -Name '7zip'

    Движок у всего это wmi а командлеты облегчают задачу.


    Грамотная постановка вопроса - уже 50% решения.
    SCCM User Group Russia на FaceBook и в Telegram

    • Помечено в качестве ответа Kupriyanov 18 июня 2018 г. 14:31
    9 июня 2018 г. 18:29
    Модератор

Все ответы

  • что-то по типу -confirm:$false не работает? что означает подтверждение сохранения, вы же не указываете где сохранять, и насколько понимаю и командлет такой параметр не принимает

    покажите как выглядит запрос

    так же было бы неплохо увидеть пример того что получаете на выходе командлета, с последним параметром и без него (у меня сейчас нет sccm для проверки). Так же было бы интересно посмотреть, появляется ли запрос если последний параметр убрать


    The opinion expressed by me is not an official position of Microsoft

    Модератор
  • Запрос выглядит вот так

    Invoke-CMReport-ReportPath"Users/Computers for a specific user name"-ReportParameter@{"user name"="test"} -OutputFormatcsv

    VERBOSE: Executing WQL query: SELECT * FROM SMS_SCI_SysResUse WHERE RoleName = 'SMS SRS Reporting Point' AND SiteCode = 'CS1'


    -confirm:$false это относится к самому PoSh. А он вопросов  не задает :)

    Видимо это тупиковая ветвь развития. Нужно что-то без браузера.

    Типа Invoke-CMQuery только нужно будет все отчеты перевести в запросы, что выглядит тоже как-то глупо.

    Есть Invoke-CMWMIQuery, но пока не нашел примеров с подстановкой параметров. Запрос отчета у меня есть, а вот как туда запихнуть переменную непонятно - ругается.

    $WQL = @"
    SELECT  SYS.User_Name0, SYS.Netbios_Name0, SYS.User_Domain0, Operating_System_Name_and0, SYS.Resource_Domain_OR_Workgr0 FROM fn_rbac_R_System($UserSid) SYS   
    WHERE User_Name0 LIKE $UserSAM
    "@
    
    Invoke-CMWmiQuery -Query $WQL
    

    Invoke-CMWmiQuery : ConfigMgr Error Object:

    instance of __ExtendedStatus

    .....

    Error Code:

    InvalidQuery

    At line:1 char:1

    + Invoke-CMWmiQuery -Query $WQL

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        + CategoryInfo          : NotSpecified: (Microsoft.Confi....InvokeWmiQuery:InvokeWmiQuery) [Invoke-CMWmiQuery], WqlQueryException

        + FullyQualifiedErrorId : UnhandledException,Microsoft.ConfigurationManagement.Cmdlets.Common.Utility.InvokeWmiQuery



  • Добрый день! В командлете Invoke-CMRepor формат вывода можно задать ключом, например :

    -OutputFormat excel

  • нет, excel - это тоже самое. Мне нужно запихнуть получившееся имя компа в переменную.

    Нужно что-то типа Invoke-CMWMIQuery.

    А Invoke-CMreport видимо просто открывает репорт - у него нет ключей для вывода в консоль. Можно настроить автоматическое сохранение в IE без запроса. Но какая-то монструозная конструкция получается. Сначала открывается IE, там генерится отчет, потом это сохраняется в файл, из него выбирается нужная инфа....

    А если сделать прямой запрос к базе (такой же как и в отчете), то должно быть так как надо.

  • Запрос у нас есть, осталось только разобраться как это делается.
  • Запрос у нас есть, осталось только разобраться как это делается.

    в зависимости от того что вы хотите делать,

    вы можете обойтись без командлета, и получить результат в формате atom (xml)

    PS C:\> $u = "http://ssrs-server.domain.local/ReportServer?%2FConfigMgr_M02%2F%D0%9F%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B8%2F%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D1%8B%20%D0%B4%D0%BB%D1%8F%20%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE%20%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F&UserFilter=s-korotkov&variable=s-korotkov&rs%3AParameterLanguage=&rs%3ACommand=Render&rs%3AFormat=ATOM&rc%3AItemPath=Table0"
    $URL = [System.Net.WebUtility]::HtmlDecode($u)
    ## '&rc:Encoding=UTF-7'
    $Response = Invoke-WebRequest -Uri ($URL + '&rc:Encoding=UTF-7') -UseDefaultCredentials -ContentType 'application/atom+xml' -ErrorAction Continue -ErrorVariable err -WarningVariable warn
    [xml]$XmlCurrent = $Response.Content
    
    $ns = @{
        d  = "http://schemas.microsoft.com/ado/2007/08/dataservices";
        m  = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
        '' = "http://www.w3.org/2005/Atom";
    }
    $Cur = Select-Xml $XmlCurrent -Namespace $ns -XPath '//m:properties'
    $Cur | select -ExpandProperty Node | ft Details_Table0_User_Name0, Details_Table0_Netbios_Name0, Details_Table0_Operating_System_Name_and0
    
    Details_Table0_User_Name0 Details_Table0_Netbios_Name0 Details_Table0_Operating_System_Name_and0
    ------------------------- ---------------------------- -----------------------------------------
    s-korotkov                S-KOR-W10-ENT                Microsoft Windows NT Workstation 10.0
    s-korotkov                S-KOR-W10-PRO                Microsoft Windows NT Workstation 10.0
    s-korotkov                S-KOR-W7-X64                 Microsoft Windows NT Workstation 6.1
    s-korotkov                S-KOR-W7-X86                 Microsoft Windows NT Workstation 6.1
    s-korotkov                S-KOR-W81-X64                Microsoft Windows NT Workstation 6.3
    s-korotkov                S-KOR-W81-X86                Microsoft Windows NT Workstation 6.3

    Как получить ссылку только на таблицу с данными:

    сформируйте отчёт, в панели инструментов нажмите "экспортировать в поток данных", откройте полученный *.atomsvc - файл, последняя ссылка - та, которая нужна.

    Надо будет только приноровиться к работе с xml объектами :)


    Грамотная постановка вопроса - уже 50% решения.
    SCCM User Group Russia на FaceBook и в Telegram


    8 июня 2018 г. 10:35
    Модератор
  • Коллега, я слабо понимаю, что делает этот скрипт, но это то, что нужно :)

    А с Invoke-CMWmiQuery или Invoke-CMQuery вы не работали?

    То есть веб запрос это по сути такой же WQL запрос к сиквельной базе SCCM.
    • Изменено Kupriyanov 9 июня 2018 г. 13:49 Уточнил
    9 июня 2018 г. 13:40
  • Коллега, я слабо понимаю, что делает этот скрипт, но это то, что нужно :)

    А с Invoke-CMWmiQuery или Invoke-CMQuery вы не работали?

    То есть веб запрос это по сути такой же WQL запрос к сиквельной базе SCCM.

    О, это просто:

    Invoke-CMWmiQuery - это просто обёртка над WMI.

    WMI-классы не полностью повторяют таблицы/вьювки (но логически очень между собой похожи), поэтому требуется некоторая адаптация и порой, в связи с ограниченностью языка запросов WMI (WQL), некоторой изобретательность :)

    Например, во sql-вьювке v_R_System (fn_rbac_R_System - это просто функция под вьювку v_R_System, с учётом ccm-прав (rbac) обратившегося пользователя), нет поля "User_Name0", есть например "LastLogonUserName". И если опираться на него то всё очень просто:

    $SearchUser = 's-korotkov'
    $query = @"
    select 
        LastLogonUserName
        ,NetbiosName
        ,OperatingSystemNameandVersion
    FROM SMS_R_SYSTEM
    WHERE LastLogonUserName = '$SearchUser'
    "@
    Invoke-CMWmiQuery -Query $query | ft 

    Чуть сложнее. Связь пользователя и компьютера через механизм UDA (User Device Affinity)

    $query = @"
    select 
        SMS_R_SYSTEM.NetbiosName
        ,SMS_R_SYSTEM.OperatingSystemNameandVersion
        ,SMS_R_User.UserName
        ,SMS_R_User.UniqueUserName
    from SMS_R_System
        JOIN SMS_UserMachineRelationship ON SMS_R_System.ResourceID = SMS_UserMachineRelationship.MachineResourceID
        JOIN SMS_R_User ON SMS_UserMachineRelationship.UniqueUserName = SMS_R_User.UniqueUserName
    WHERE SMS_R_User.UserName = '$SearchUser'
    "@
    
    $Res = Invoke-CMWmiQuery -Query $query
    $Res | select @{n="NetbiosName"; e={$_.SMS_R_SYSTEM.NetbiosName}}, @{n="UserName"; e={$_.SMS_R_User.UserName}},@{n="OS Name"; e={$_.SMS_R_SYSTEM.OperatingSystemNameandVersion}}




    9 июня 2018 г. 17:48
    Модератор
  • Коллега, я слабо понимаю, что делает этот скрипт, но это то, что нужно :)

    А с Invoke-CMWmiQuery или Invoke-CMQuery вы не работали?

    То есть веб запрос это по сути такой же WQL запрос к сиквельной базе SCCM.

    ах, да...

    Invoke-CMQuery - тут вообще всё просто и гениально, вы пишете запрос (query) в консоли: \Monitoring\Overview\Queries\

    а командлетом Invoke-CMQuery выполняете его и получаете результат.

    Invoke-CMQuery -Name '7zip'

    Движок у всего это wmi а командлеты облегчают задачу.


    Грамотная постановка вопроса - уже 50% решения.
    SCCM User Group Russia на FaceBook и в Telegram

    • Помечено в качестве ответа Kupriyanov 18 июня 2018 г. 14:31
    9 июня 2018 г. 18:29
    Модератор
  • Огромное спасибо, я посмотрю ваши примеры.

    Как я понял, для Invoke-CMQuery -Name '7zip' нужно скопировать запрос из нужного отчета в \Monitoring\Overview\Queries\, а напрямую по имени отчета командлет не может работать?

    13 июня 2018 г. 15:16
  • Огромное спасибо, я посмотрю ваши примеры.

    Как я понял, для Invoke-CMQuery -Name '7zip' нужно скопировать запрос из нужного отчета в \Monitoring\Overview\Queries\, а напрямую по имени отчета командлет не может работать?

    Как я понял, для Invoke-CMQuery -Name '7zip' нужно скопировать запрос из нужного отчета в \Monitoring\Overview\Queries\, - Не совсем. Invoke-CMQuery выполнит созданный Query, но скопировать его из отчёта не получится.

    скопировать запрос из нужного отчета: Отчёт к SCCM, по большому счёту, отношения не имеет, это SSRS (SQL Server Reporting Services) сервис который берёт данных из SQL-базы, т.е. это SQL-запрос. А SCCM Query - это WQL (WMI Query Language) запрос. Технически совершенно разные вещи, хотя имеют схожий подход к именованию.

    Если подытожить: Хотите дергать данные через SSRS (из отчётов) - используйте пример из первого сркипта с Invoke-WebRequest. Хотите работать с WMI объектами CCM - Invoke-CMQuery.


    Грамотная постановка вопроса - уже 50% решения.
    SCCM User Group Russia на FaceBook и в Telegram

    13 июня 2018 г. 16:46
    Модератор
  • PS C:\> $u = http://ssrs-server.domain.local/ReportServer?%2FConfigMgr_M02%2F%D0%9F%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B8%2F%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D1%8B%20%D0%B4%D0%BB%D1%8F%20%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE%20%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F&UserFilter=s-korotkov&variable=s-korotkov&rs%3AParameterLanguage=&rs%3ACommand=Render&rs%3AFormat=ATOM&rc%3AItemPath=Table0

    Как оказалось в этой строчке нужно ввести не SamAccountName, a что-то из переменных sccm.

    То есть вместо UserFilter=s-korotkov он понимает SamAccountName, а вместо variable=s-korotkov ему нужна переменная из SCCM.

    В моем случае, если SamAccountName=user, то variable может быть USER, а для отчета это имеет разницу. и он не показывает ничего...
    Точнее

    Default value or value provided for the report parameter 'variable' is not a valid value. (rsInvalidReportParameter)




    • Изменено Kupriyanov 15 июня 2018 г. 8:46
    15 июня 2018 г. 8:45
  • Попробовал в отчете поставить Case Sensitivity=false. Без изменений, все равно отчет остается регистро-чувствительным.

     
    18 июня 2018 г. 13:19
  • Попробовал в отчете поставить Case Sensitivity=false. Без изменений, все равно отчет остается регистро-чувствительным.

     

    Недеюсь вы не родной отчёт правите :)

    чтобы упростить отчёт:

    1.удалите Dataset - "DataSet1" - это запрос пользователей для фильтра

    2. удалите переменную - "UserFilter"

    3. в переменной - "variable", на вкладке "Available Value" переключите значение на "None"

    Ну или вот готовый: Компьютеры для определенного имени пользователя.rdl


    Грамотная постановка вопроса - уже 50% решения.
    SCCM User Group Russia на FaceBook и в Telegram

    18 июня 2018 г. 13:37
    Модератор
  • Второй вариант привести все логины к одному регистру в фильтре (dataset "UserFilter"), что-то вроде этого:
    begin
        if (@filterwildcard = '') 
        SELECT DISTINCT LOWER(SYS.User_Name0)
        from fn_rbac_R_System(@UserSIDs)  SYS
        Order by 1
    else 
    SELECT DISTINCT LOWER(SYS.User_Name0)
        from fn_rbac_R_System(@UserSIDs)  SYS
        WHERE SYS.User_Name0 like @filterwildcard
        Order by 1
    end


    Грамотная постановка вопроса - уже 50% решения.
    SCCM User Group Russia на FaceBook и в Telegram

    18 июня 2018 г. 14:06
    Модератор
  • Первый вариант подошел, сейчас второй опробую.

    Не успел пометить "как ответ" ваши ответы, но полностью поддерживаю решение модератора.


    • Изменено Kupriyanov 18 июня 2018 г. 14:36
    18 июня 2018 г. 14:36
  • Вот с LOWER не работает, не дает сохранить даже :)
    18 июня 2018 г. 14:55
  • Вот с LOWER не работает, не дает сохранить даже :)

    Ну тут приноровится надо к report builder-у, он порой считает себя умнее всех :)

    Тут правда и отчёт - так себе сделан. Иногда проще отредактировать rdl-файл в блокноте.

    Ну и запрос я дал для примера, в таком виде не заработает.

    Там и заголовка нет, а он в Field-ах аж дважды задан (не понятно зачем).

    Целиком:

    -- DECLARE @filterwildcard NVARCHAR(max) =  N'', @UserSIDs NVARCHAR(max) =  N'disabled'
    begin
        if (@filterwildcard = '') 
        SELECT DISTINCT LOWER(SYS.User_Name0) as User_Name0
        from fn_rbac_R_System(@UserSIDs)  SYS
        Order by User_Name0
    else 
    SELECT DISTINCT LOWER(SYS.User_Name0) as User_Name0
        from fn_rbac_R_System(@UserSIDs)  SYS
        WHERE SYS.User_Name0 like @filterwildcard and SYS.User_Name0 is not null
        Order by User_Name0
    end

    отчёт: Компьютеры для определенного имени пользователя(lower).rdl

    Грамотная постановка вопроса - уже 50% решения.
    SCCM User Group Russia на FaceBook и в Telegram

    18 июня 2018 г. 18:59
    Модератор